简化树删除节点

时间:2017-11-05 10:16:48

标签: r igraph tidygraph

我有一个可以被视为树的非循环图。这是一个简单的例子:

library(tidygraph)
create_tree(20,2, directed = TRUE, mode="in") %>% plot

is

现实生活中的例子可能有点复杂,因为我可能有从叶子到根的多条路径(所有这些路径都是非循环的)。

我想通过删除中间节点来简化图形,如下所示:

K = 0

在最极端的情况下(让我们称之为" k = 0"简化)我会枚举所有叶子,确保它们通过深度优先搜索连接到根,然后有效地删除所有中间连接将每个叶子链接到根。

K = -1

下一级简化(比如" k = -1")我想从至少有一个叶子节点的节点开始并重复相同的过程。 简化后,将删除所有中间节点:

data.frame(from=c(5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20),
           to = c(1,1,1,1,1, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,10)) %>% 
  as_tbl_graph() %>% plot

want

K = -2

简化的下一步对于此图没有意义,因为不会修改任何边,也不会删除任何节点。

如何使用R?

中的igraph / tidygraph对其进行编码

1 个答案:

答案 0 :(得分:0)

解决方案最重要的部分是能够将叶子中的节点枚举回根,有效地测量距离最近叶子的距离"

使用与上面相同的示例,让我们添加节点名称(create_tree()不会产生节点,原因有些奇怪):

library(tidygraph)

graph <- create_tree(20,2, directed = TRUE, mode="in") %>% 
  activate(nodes) %>% mutate(name=1:n())

我们需要一个辅助函数来测量与叶子的距离&#34;:

make_levels <- function(grdf){
  i <- 0
  repeate <- TRUE
  # create helper column
  grdf <- grdf %>% 
    mutate(leaf = node_is_leaf(),
           level=ifelse(leaf, i, NA))

  while(repeate){
  i <- i + 1
  index <- grdf %>% activate(edges) %>%
    mutate(from_leaf=.N()$leaf[from]) %>% 
    as_tibble() %>% filter(from_leaf) %>% pull(to)

  grdf <- grdf %>% activate(nodes) %>% 
    mutate(leaf = 1:n() %in% index,
           level=ifelse(leaf & is.na(level), i, level))

  repeate <- grdf %>% activate(nodes) %>% 
    as_tibble() %>% pull(level) %>% is.na() %>% any()
  }
  # remove helper column
  grdf %>% activate(nodes) %>% select(-leaf)    
}

在此之后,解决方案(上面的k=-1)应该很简单:

graph %>% make_levels() %>% activate(edges) %>% 
  reroute(from = from, to = 1, subset=(to %in% which(.N()$level==2))) %>% 
  activate(nodes) %>% filter(level!=2) %>% plot()

产生:

done