【发布时间】:2014-05-23 22:23:05
【问题描述】:
我有一个 data.frame,其中两列代表一棵分层树,有父节点和节点。
我想转换它的结构,使其可以用作d3tree 函数的输入,来自d3Network 包。
这是我的数据框:
df <- data.frame(c("Canada","Canada","Quebec","Quebec","Ontario","Ontario"),c("Quebec","Ontario","Montreal","Quebec City","Toronto","Ottawa"))
names(df) <- c("parent","child")
我想把它改造成这种结构
Canada_tree <- list(name = "Canada", children = list(
list(name = "Quebec",
children = list(list(name = "Montreal"),list(name = "Quebec City"))),
list(name = "Ontario",
children = list(list(name = "Toronto"),list(name = "Ottawa")))))
我已经使用下面的代码成功地转换了这个特殊情况:
fill_list <- function(df,node) node <- as.character(node)if (is.leaf(df,node)==TRUE){
return (list(name = node))
}
else {
new_node = df[df[,1] == node,2]
return (list(name = node, children = list(fill_list(df,new_node[1]),fill_list(df,new_node[2]))))
}
问题是,它只适用于每个父节点正好有两个孩子的树。 您可以看到我将两个孩子(new_node[1] 和 new_node[2])硬编码为递归函数的输入。
我正在尝试找出一种方法,可以像调用父节点的子节点一样多次调用递归函数。 示例:
fill_list(df,new_node[1]),...,fill_list(df,new_node[length(new_node)])
我尝试了这 3 种可能性,但都没有奏效:
首先:创建一个包含所有函数和参数的字符串,然后进行评估。它返回此错误could not find function fill_functional(df,new_node[1])。那是因为我的函数在我调用它的时候还没有创建。
fill_functional <- function(df,node) {
node <- as.character(node)
if (is.leaf(df,node)==TRUE){
return (list(name = node))
}
else {
new_node = df[df[,1] == node,2]
level <- length(new_node)
xxx <- paste0("(df,new_node[",seq(level),"])")
lapply(xxx,function(x) eval(call(paste("fill_functional",x,sep=""))))
}
}
第二:使用for循环。但我只得到了根节点的子节点。
L <- list()
fill_list <- function(df,node) {
node <- as.character(node)
if (is.leaf(df,node)==TRUE){
return (list(name = node))
}
else {
new_node = df[df[,1] == node,2]
for (i in 1:length(new_node)){
L[i] <- (fill_list(df,new_node[i]))
}
return (list(name = node, children = L))
}
}
第三:创建一个用函数元素填充列表的函数,并且只更改参数。但我没能完成任何有趣的事情,而且我担心我会遇到与上述第一次尝试相同的问题。
【问题讨论】:
标签: r list dataframe tree networkd3