从头到尾生成顺序配对值的不同长度向量

时间:2018-03-21 10:13:06

标签: r vector binary-tree parent children

如果之前已经提出这个问题,我会道歉 - 我正在努力思考如何对我的搜索进行评论(因此这个尴尬的标题)!

我所拥有的是单字符值的数据框,如下所示:

-------------------------
|  Parent  |  Daughter  |
-------------------------
|     A    |     B      |
|     B    |     C      |
|     B    |     D      |
|     A    |     E      |
-------------------------

每个父母的位置总会有两个女儿(如完整的二叉树)。我试图编写一段代码,用于生成从顶级父级到最终子级的路径向量:

A B C
A B D
A E

但是父母的数量不同,载体的长度也各不相同。

我考虑过使用for循环,但是因为我觉得我需要每个级别都有一个问题。这棵树,我事先不知道。

我不一定想要代码,只是建议如何解决这个问题!但是,非常感谢任何帮助,谢谢!

编辑:我应该指出“从结束开始”'只是因为我认为这样会更容易 - 这当然不是必要的!

数据:

df <- data.frame(Parent = c("A", "B", "B", "A"), Daughter = c("B", "C", "D", "E"))

EDIT2:以下是所需结果的更多示例。如果我把桌子做得更大,那么:

-------------------------
|  Parent  |  Daughter  |
-------------------------
|     A    |     B      |
|     B    |     C      |
|     B    |     D      |
|     A    |     E      |
|     C    |     F      |
|     C    |     G      |
|     E    |     H      |
|     E    |     I      |
-------------------------

数据2:

df <- data.frame(Parent = c("A", "B", "B", "A", "C", "C", "E", "E"), Daughter = c("B", "C", "D", "E", "F", "G", "H", "I"))

然后我想要的载体是:

A B C F
A B C G
A B D
A E H
A E I

2 个答案:

答案 0 :(得分:3)

使用 igraph 包,将数据帧转换为图形对象,获取路径,删除作为其他路径子集的路径。

library(igraph)

# example data
df <- data.frame(Parent = c("A", "B", "B", "A", "C", "C", "E", "E"), 
                 Daughter = c("B", "C", "D", "E", "F", "G", "H", "I"))

# convert to graph object
g <- graph_from_data_frame(df)

# get all the paths, extract node ids from paths
res <- all_simple_paths(g, from = "A")
res <- lapply(res, as_ids)

# get index where vector is not subset of other vector
ix <- sapply(res, function(i) {
  x <- sapply(res, function(j) length(intersect(i, j)))
  sum(length(i) == x) == 1
})

# result
res <- res[ix]
# res
# [[1]]
# [1] "A" "B" "C" "F"
# 
# [[2]]
# [1] "A" "B" "C" "G"
# 
# [[3]]
# [1] "A" "B" "D"
# 
# [[4]]
# [1] "A" "E" "H"
# 
# [[5]]
# [1] "A" "E" "I"

答案 1 :(得分:1)

这可能会有所帮助:

parent <- "A"
lev <- df$Daughter[which(df$Parent == parent)]
output <- cbind(parent, lev)
while(length(lev) > 0){
    lev <- df$Daughter[which(is.element(df$Parent, lev))]
    output <- cbind(output, lev)
}
# which returns
> output
     parent lev lev
[1,] "A"    "B" "C"
[2,] "A"    "E" "D"

这很容易转换为function(parent)

myfct <- function(parent){

  lev <- df$Daughter[which(df$Parent == parent)]
  output <- data.frame(parent, lev, stringsAsFactors = F)

  while(length(lev) > 0){

    dat <- df[which(is.element(df$Parent, lev)),]
    newdat <- merge(x = output, y = dat, by.x = "lev", by.y = "Parent", all = TRUE)

    col.first <- which(names(newdat) == "parent")
    col.last <- which(names(newdat) == "Daughter")
    col.sec.last <- which(names(newdat) == "lev")
    col.rest <- setdiff(1:dim(newdat)[2], c(col.first, col.sec.last,col.last))

    newdat <- newdat[, c(col.first, col.rest, col.sec.last, col.last)]
    names(newdat)[2:(length(names(newdat))-1)] <- paste0("x.",2:(length(names(newdat))-1))
    names(newdat)[length(names(newdat))] <- "lev" 


    output <- newdat

    lev <- df$Daughter[which(is.element(df$Parent, lev))]
  }
  cols <- as.numeric(which(!sapply(output, function(x)all(is.na(x)))))
  output <- output[,cols]
  return(output)
}

这里可以应用这个功能:

parents.list <- unique(df$Parent)
sapply(parents.list, myfct)
# which returns
$A
  parent x.2 x.3  x.4
1      A   B   C    F
2      A   B   C    G
3      A   B   D <NA>
4      A   E   H <NA>
5      A   E   I <NA>

$B
  parent x.2  x.3
1      B   C    F
2      B   C    G
3      B   D <NA>

$C
  parent x.2
1      C   F
2      C   G

$E
  parent x.2
1      E   H
2      E   I

现在您可以随时修改它以更改输出的结构。

修改

关键是添加while。我编辑了我的代码,现在它应该工作而不必指定级别数。