【问题标题】:Pruning / Retrieving Nodes from a Tree Based on Parent / Child / Sibling Relationships基于父/子/兄弟关系从树中修剪/检索节点
【发布时间】:2014-06-10 01:37:05
【问题描述】:

我有一个树结构,其中包含唯一标识的节点、一个根和一堆分支。任何节点可以发芽的分支数量或分支深度都没有限制。

我想做的是,给定一个节点的 id,有效地返回该节点的所有父节点的 id,以及每个父节点的所有兄弟姐妹的 id。我希望这个特定问题的答案将使用为这种类型的操作设计的包/函数,以便我可以了解它们并将它们用于未来的类似问题,而不是每次都必须编写自定义算法。

这是子父形式的树:

structure(list(child = 1:20, parent = c(NA, 1L, 2L, 3L, 1L, 5L, 6L, 5L, 8L, 1L, 1L, 11L, 12L, 11L, 14L, 14L, 1L, 17L, 18L, 19L)), .Names = c("child", "parent"), class = "data.frame", row.names = c(NA, -20L))

这是一个视觉表示:

对于特定问题,我的目标 id 是 13(红色),并且想获取父节点的 id(橙色)以及父节点的兄弟姐妹的 id(黄色)。我绝对可以想出一个算法来做到这一点(获取所有父母很容易,然后兄弟姐妹意味着获取每个父母的父母的孩子),但我真的希望已经存在一个框架可以有效地完成这一切。

我简要地研究了rparttreeape,但据我的简短回顾可以看出,它们的目标是树的统计分类,而不是节点的操作/检索,它似乎我基于一个有点敷衍的评论,他们不提供我所追求的功能(很可能我只是错过了它/误解了它)。

另一个选项似乎是 XMLxmlTree,这将允许我使用一些 DOM 操作工具来实现我的目标,但它似乎有点笨拙,可能不是最佳选择。

【问题讨论】:

  • 我想你想要 'igraph' 包。
  • @BondedDust,是的,谢谢,这就是我想要的,虽然需要一些工作。

标签: r tree igraph


【解决方案1】:

我多次发现自己处于类似情况,而且我通常只是推出自己的解决方案。我同意 XML 包对于诸如此类的重点问题来说太过分了。 iGraph 包很好,但要小心。它是 C 库的接口并且是零索引的(不像 R 是 1 索引的)。我已经成功使用它,但似乎总是有一个痛苦的调试过程,在这个过程中我一直在寻找“未移位”的索引。 (例如,foo[index] 必须更改为 foo[index-1]。)

再一次,我可能会自己动手。比如:

foo <- structure(list(child = 1:20, parent = c(NA, 1L, 2L, 3L, 1L, 5L, 6L, 5L, 8L, 1L, 1L, 11L, 12L, 11L, 14L, 14L, 1L, 17L, 18L, 19L)), .Names = c("child", "parent"), class = "data.frame", row.names = c(NA, -20L))

get_ancestry <- function(node, data=foo, ancestry=c()) {
    parent <- data$parent[data$child %in% node]
    if (is.na(parent)) {
        return(ancestry)
    } else {
        get_ancestry(parent, data, c(ancestry, parent))
    }
}

get_children <- function(nodes, data=foo) {
    unlist(lapply(nodes, function(x) {data$child[data$parent %in% x]}))
}

orange <- get_ancestry(13)
yellow <- get_children(orange)

【讨论】:

  • 除非有人从igraph 中找出更明显的功能,否则由于需要进行所有后处理,您的解决方案似乎与我发布的解决方案一样好/更好。
  • FWIW,igraph 的 R 接口不再是 0 索引(从 0.6 版开始)。
  • @Tamás,感谢您提供的信息;我不知道。使 igraph 包成为未来树/图问题更理想的选择。
【解决方案2】:

感谢您的指点,igraph 绝对是我正在寻找的东西,尽管我在那里有点不知所措。在python igraph tutorial 的帮助下,我得到了:

g <- graph(t(as.matrix(df[-1, 2:1])))            # Make graph
plot(g)                                          # yes, this matches mine
parents <- unlist(                               # orange nodes  
  neighborhood(
    g, 
    order=ecount(g),                             # how many steps to go up, this should guarantee we get to root  
    nodes=13,                                    # starting point    
    mode="in"                                    # head in towards root
  )
)[-1L]
setdiff(                                         # yellow nodes  
  unique(                                        
    unlist(
      lapply(parents, neighborhood, graph=g, order=1, mode="out")
  ) ),
  c(parents, 13)
)

这会产生所需的答案。不幸的是,由于neighborhood 函数的返回格式,每一步都需要进行一些后期处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 2011-04-27
    • 1970-01-01
    相关资源
    最近更新 更多