我有一个可以被视为树的非循环图。这是一个简单的例子:
library(tidygraph)
create_tree(20,2, directed = TRUE, mode="in") %>% plot
现实生活中的例子可能有点复杂,因为我可能有从叶子到根的多条路径(所有这些路径都是非循环的)。
我想通过删除中间节点来简化图形,如下所示:
在最极端的情况下(让我们称之为" k = 0"简化)我会枚举所有叶子,确保它们通过深度优先搜索连接到根,然后有效地删除所有中间连接将每个叶子链接到根。
下一级简化(比如" 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
简化的下一步对于此图没有意义,因为不会修改任何边,也不会删除任何节点。
如何使用R?
中的igraph
/ tidygraph
对其进行编码
答案 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()
产生: