从树递归创建data.frame的正确方法

从树递归创建data.frame的正确方法,r,recursion,tree,R,Recursion,Tree,我想从R中的树创建一个平面data.frame 树由一个列表表示,每个列表都包含一个名为children的键,该键包含更多具有更多子级的列表 tree <- list(name="root", parent_name='None', children=list( list(parent_name="root", name="child1", children=list()), list(parent_name="root"

我想从R中的树创建一个平面
data.frame

树由一个列表表示,每个列表都包含一个名为
children
的键,该键包含更多具有更多子级的列表

tree <-
  list(name="root",
       parent_name='None',
       children=list(
         list(parent_name="root", name="child1", children=list()),
         list(parent_name="root", name="child2", children=list(list(parent_name="child2", name="child3", children=c())))
       )
      )
我可以使用以下递归函数完成此操作:

walk_tree <- function(node) {
  results <<- rbind(
    results,
    data.frame(
      name=node$name,
      parent_name=node$parent_name,
      stringsAsFactors=FALSE
    )
  )

  for (node in node$children) {
    walk_tree(node)
  }
}
results <- NULL
walk_tree(tree)
results # now contains the data.frame as desired
此外,使用
您不远:),使用
dplyr::bind_行

walk_tree <- function(node) {
  dplyr::bind_rows(
    data.frame(
      name=node$name,
      parent_name=node$parent_name,
      stringsAsFactors=FALSE),
    lapply(node$children,walk_tree)
  )
}

walk_tree(tree)

    name parent_name
1   root        None
2 child1        root
3 child2        root
4 child3      child2

walk_tree一种方法是将所有具有“name”和“parent_name”的节点聚集在一起,并用它们创建一个数据帧

#Flatten the nested structure
u_tree <- unlist(tree)

#Gather all the indices where name of the node is equal to parent_name
inds <- grepl("parent_name$", names(u_tree))

#Add them in a dataframe
data.frame(name = u_tree[!inds], parent_name = u_tree[inds])

#    name parent_name
#    root        None
#2 child1        root
#3 child2        root
#4 child3      child2
#展平嵌套结构

u_tree您可以使用ape
软件包中优秀的树结构,以括号格式写入数据(逗号(
)表示顶点,括号表示边,叶子是“子”——树以分号(
)结尾)

您可以向任何子级添加额外的结构(树),如下所示:

child1_children <- ape::read.tree(text = "(child4, (child5, child6));")
## Adding child1_children to the first leave
tree2 <- ape::bind.tree(tree, child1_children, where = 1)
## Plotting the tree
plot(tree2)
ape::nodelabels()
tree2$edge
#     [,1] [,2]
#[1,]    6    7
#[2,]    7    3
#[3,]    7    8
#[4,]    8    4
#[5,]    8    5
#[6,]    6    9
#[7,]    9    1
#[8,]    9    2

child1\u children@RonakShah是的,这很有效!想发布一个答案,这样我就可以标记它吗?@RonakShah事实上,我很好奇这是否会达到深度嵌套树的限制。我将首先编写更多的测试。无论树的深度如何,只要它们遵循命名约定(“name”和“parent_name”)。我仔细检查了一下,它对我来说运行良好。我真的不知道如何调试这个。。。其他人有这个问题吗?如果你有上面提到的问题,请在否决投票前发表评论,我不能盲目地修正它。我把这个作为正确的答案,因为它是最容易理解的,并且带有一个基本的R解决方案。谢谢我正在从API中卷曲树数据,因此不能简单地重新编写格式。
walk_tree <- function(node) {
  do.call(
    rbind,
    c(
    list(data.frame(
      name=node$name,
      parent_name=node$parent_name,
      stringsAsFactors=FALSE)),
    lapply(node$children,walk_tree)
  ))
}

walk_tree(tree)
#Flatten the nested structure
u_tree <- unlist(tree)

#Gather all the indices where name of the node is equal to parent_name
inds <- grepl("parent_name$", names(u_tree))

#Add them in a dataframe
data.frame(name = u_tree[!inds], parent_name = u_tree[inds])

#    name parent_name
#    root        None
#2 child1        root
#3 child2        root
#4 child3      child2
## Reading a tree
my_tree <- "(child1, (child2, child3));"
tree <- ape::read.tree(text = my_tree)

## Getting the edge table (your flatten format)
tree$edge
#     [,1] [,2]
#[1,]    4    1
#[2,]    4    5
#[3,]    5    2
#[4,]    5    3
## Plotting the tree
plot(tree)
ape::nodelabels()
child1_children <- ape::read.tree(text = "(child4, (child5, child6));")
## Adding child1_children to the first leave
tree2 <- ape::bind.tree(tree, child1_children, where = 1)
## Plotting the tree
plot(tree2)
ape::nodelabels()
tree2$edge
#     [,1] [,2]
#[1,]    6    7
#[2,]    7    3
#[3,]    7    8
#[4,]    8    4
#[5,]    8    5
#[6,]    6    9
#[7,]    9    1
#[8,]    9    2
rev(data.frame(matrix(stack(tree)[,1],,2,T)))#MHHH seems too easy for the task
      X2     X1
1   None   root
2 child1   root
3 child2   root
4 child3 child2

stack(tree)%>%
mutate(new=rep(1:(n()/2),each=2),ind=rep(ind[2:1],n()/2))%>%
spread(ind,values)
  new   name parent_name
1   1   None        root
2   2 child1        root
3   3 child2        root
4   4 child3      child2