我想使用R中的data.tree
库将edgelist转换为树对象。
这是我的代码:
library(data.tree)
edges <- read.csv("data.csv")
colnames(edges) <- c("source", "target")
R1 <- data.frame(Parent=edges$source, Child=edges$target)
R2<- data.frame(Parent=c("earth","earth","forest","forest","ocean","ocean","ocean","ocean"),
Child=c("ocean","forest","tree","sasquatch","fish","seaweed","mantis shrimp","sea monster"))
现在,如果我运行tree <- FromDataFrameNetwork(R2)
,事情就会发挥作用。但如果我tree <- FromDataFrameNetwork(R1)
,我会收到以下错误:
Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
Error during wrapup: evaluation nested too deeply: infinite recursion / options(expressions=)?
这怎么可能?
R1看起来像这样:
Parent Child
1 1 6
2 4 2
3 3 5
4 1 4
5 1 5
6 5 3
R2看起来像这样:
Parent Child
1 earth ocean
2 earth forest
3 forest tree
4 forest sasquatch
5 ocean fish
6 ocean seaweed
7 ocean mantis shrimp
8 ocean sea monster
答案 0 :(得分:0)
正如@lukeA所说,R1包含一个循环关系。如果3是5的父级,而5是3的父级,则FromDataFrameNetwork(R1)
将在尝试构建树时无限递归。您可以编写一个递归帮助函数来验证要转换为树的表,例如:
library(tidyverse)
validate <- function(origin, tree, ancestors = character()){
ancestors = c(ancestors, origin)
kids <- tree %>%
filter(Parent == origin) %>%
select(Child) %>%
pull()
invalid.kids <- kids[kids %in% ancestors] # if any Child appears in its own ancestry, then it's invalid
if(length(invalid.kids)){
print(paste('invalid children:',
paste(invalid.kids, collapse = ', '),
'parent:',
origin)) # print Children that produce circular relationships for debugging
}
children <- lapply(kids[!(kids %in% ancestors)], validate, tree, ancestors) # recursively apply validate() to all valid Children
tree <- filter(tree, !(Child %in% invalid.kids)) # key step: filter out parts that would cause an infinite loop
return(rbind(tree, do.call(rbind, children)))
}
警告:我还没有测试这个确切的脚本,但是过去我使用过类似的方法。