【问题标题】:Converting an edgelist to data.tree将边缘列表转换为 data.tree
【发布时间】:2017-05-13 18:31:44
【问题描述】:

我想使用 R 中的 data.tree 库将边缘列表转换为树对象。

这是我的代码:

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 &lt;- FromDataFrameNetwork(R2),一切正常。但是如果我这样做tree &lt;- 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

【问题讨论】:

  • 在 R1 中,3 是 5 的父节点,5 是 3 的父节点。这怎么可能在树中?

标签: r dataframe tree


【解决方案1】:

正如@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)))
}

注意:我没有测试过这个确切的脚本,但我过去使用过类似的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-15
    • 2019-02-16
    • 2021-11-22
    • 2020-01-30
    相关资源
    最近更新 更多