将树转换为R中的data.frame

时间:2014-08-05 11:51:03

标签: r dataframe tree-traversal

在我自己编写之前,我想知道是否有一个功能已经这样做了:

我有一个树结构,实现为嵌套的列表列表。每个节点都有一些内部数据(例如它的名字),以及一个儿子列表,它们又包含一些节点数据和另一个儿子列表等。树是完整的,即所有分支都已满并且相同的长度。

我想遍历树以创建每行包含的data.frame 树的一个分支上的完整数据,包括所有分支

所以对于在根下面有2个1级节点的树(名为a,b),每个节点都有两个儿子(名为c,d代表节点a,e代表f代表noe b)我的data.frame应该看起来像:

## root a  c
## root a  d
## root b  e
## root b  f

列表结构可能如下所示:

tree = list(list(name = "a", sons = list(list(name = "c"),list(name="d"))),
            list(name = "b", sons = list(list(name = "e"),list(name="f"))))

遍历是基本的,我可以自己写,但讨厌发明现有的东西

那里有什么东西吗?

感谢。

1 个答案:

答案 0 :(得分:0)

好的 - 抱歉回答我自己的问题。 在给出更多想法后,我写了一个相当通用的代码。它假定一个包含嵌套列表的结构,使得在每个级别都需要提取某些字段,并遵循包含后代元素列表的字段。假设在同一级别的所有节点在提取的字段和在哪里寻找后代方面看起来相同。在这些假设下,遍历可以使用三个参数进行编码:

root - 完整的数据 extract - 字段名称列表。每个列表条目是关于要在给定级别提取的数据的字段名称/索引的向量 follow - 字段名称/索引列表,告诉我们在哪个位置查找每个级别的后代列表。

代码:

tt2df = function(root,extract = 1,follow=2,level=1) {
if(is.null(root)) return(NULL)
n= length(extract)
if(n==0) return(NULL)
if(level>n) return(NULL)
if (length(follow)!=n) stop("extract and follow do not match")
vals = unlist(root[extract[[level]]])
sons = tryCatch(root[[follow[[level]]]],error=function(s) return(NULL))
if(n==level) {
    return(data.frame(t(vals)))
}
temp = data.frame(do.call(rbind,lapply(1:length(sons), function(x) {
        son = sons[[x]]
        res = tt2df(son,extract,follow,level+1)
        nm = paste(follow[[level]],level,sep=".")
        res[[nm]] = x
        return(res)
        })))
for(x in names(vals)) {
nx = x
if(x %in% names(temp))
nx = paste(x,level,sep=".")
temp[[nx]] = vals[x]
}
return(temp)
}

我没有仔细检查过,但它适用于我的一些例子,有些相当复杂。人们也可以使它更美观/更有效率。我欢迎评论/改进

我觉得遍历解析的JSON文件特别有用。 随意使用它需要您自担风险。但如果你发现它有用/有问题,请告诉我