如何在ggraph分面中仅保留各面板的关联节点?
解决ggraph分面弧图显示孤立节点的问题
问题根源在于facet_edges()仅对边进行分面过滤,不会自动过滤节点,因此所有节点会显示在每个面板中。以下是两种可行的解决方案:
方案一:拆分子图后用patchwork拼接(直观可靠)
通过为每个分面分组单独生成子图,确保每个子图仅包含对应分组的边和关联节点,再拼接成整体图。
library(tidyverse) library(tidygraph) library(ggraph) library(patchwork) # 原始数据 myedges <- data.frame(from=rep(letters[1:5],2), to=c(rep(LETTERS[12:13],2), rep(LETTERS[14],3), LETTERS[15:16], LETTERS[17]), n_user=sample(1:20, 10, replace=TRUE), f=rep(c("face_A", "face_B"),5) ) # 按f分组拆分边数据 edge_groups <- split(myedges, myedges$f) # 遍历每个分组生成对应绘图 plot_list <- map(edge_groups, function(edges) { # 提取当前分组的所有节点并计算n_user nodes <- edges %>% pivot_longer(cols = c(from, to), names_to = "od", values_to = "node_name") %>% group_by(node_name) %>% summarise(n_user = sum(n_user), .groups = "drop") # 构建子图 sub_graph <- tbl_graph(nodes = nodes, edges = edges) # 绘制弧图 ggraph(sub_graph, layout = 'linear') + geom_edge_arc(aes(edge_width=n_user, label=n_user), label_pos=0.1, edge_alpha=0.2)+ geom_node_point(aes(size=n_user), alpha=0.5, show.legend = FALSE)+ geom_node_text(aes(label = node_name), size=3, nudge_y = -0.5)+ labs(title = unique(edges$f)) + theme_minimal() }) # 拼接所有绘图(按列排列) plot_list[[1]] + plot_list[[2]] + plot_layout(ncol = 1)
方案二:给节点添加分面标记,绘图时过滤节点(原生分面)
通过给节点标记其所属的分面分组,在绘图时仅显示当前面板对应的节点,无需额外拼接工具。
library(tidyverse) library(tidygraph) library(ggraph) # 原始数据 myedges <- data.frame(from=rep(letters[1:5],2), to=c(rep(LETTERS[12:13],2), rep(LETTERS[14],3), LETTERS[15:16], LETTERS[17]), n_user=sample(1:20, 10, replace=TRUE), f=rep(c("face_A", "face_B"),5) ) # 重新处理节点数据,标记每个节点出现的分面分组 mynodes <- myedges %>% pivot_longer(cols = c(from, to), names_to = "od", values_to = "node_name") %>% group_by(node_name) %>% summarise( n_user = sum(n_user), # 记录节点所属的所有分面分组 facets = list(unique(f)) ) # 构建图对象 g <- tbl_graph(nodes = mynodes, edges = myedges) # 绘图时过滤节点,仅显示当前面板对应的节点 ggraph(g, layout = 'linear') + geom_edge_arc(aes(edge_width=n_user, label=n_user), label_pos=0.1, edge_alpha=0.2)+ # 利用after_stat(panelvar1)获取当前面板的分面值,过滤节点 geom_node_point(aes(size=n_user, filter = after_stat(panelvar1) %in% facets), alpha=0.5, show.legend = FALSE)+ geom_node_text(aes(label = node_name, filter = after_stat(panelvar1) %in% facets), size=3, nudge_y = -0.5)+ facet_edges(facets = vars(f), scales = "free") + theme_minimal()
内容的提问来源于stack exchange,提问作者maxbre
相关产品推荐
相关产品推荐

