如何在ggraph中固定节点位置以生成可对比的多样网络?
固定节点位置的对比网络图谱实现方案
需求说明
需要生成多幅以指定节点为中心的网络图谱,满足以下要求:
- 所有节点(含中心节点)的位置固定,便于不同网络间直观对比
- 当前网络未涉及的节点显示为灰色(半透明)状态
- 节点按固定顺序环绕中心节点排列
实现步骤
- 预定义全局节点集合:先提取所有唯一节点并按固定顺序排序,确保所有图谱的节点基础集合一致
- 生成固定布局:针对每个中心节点,预先生成圆形focus布局并保存坐标,保证不同图谱的节点位置完全匹配
- 节点状态标记:在节点数据中添加标记,区分当前网络包含的节点和未涉及节点,未涉及节点设置为灰色半透明
- 边数据过滤:仅保留与当前中心节点相关的边,无关边不渲染
- 统一视觉样式:统一节点大小、标签样式、边的配色和宽度,保证多图对比的一致性
修改后的完整代码
library(tidyverse) library(ggraph) library(tidygraph) set.seed(1234) # 原始边数据 links_all = tibble::tribble( ~x, ~input, ~output, ~direction, ~weight, 2, "Group3", "Group4", "positive", 0.55076, 3, "Group3", "Group5", "positive", 0.25263, 4, "Group3", "Group7", "positive", 0.14137, 5, "Group3", "Group8", "positive", 0.1532, 6, "Group3", "Group6", "positive", 0.51479, 7, "Group3", "Group9", "positive", 0.2315, 8, "Group3", "Group1", "positive", 0.21106, 9, "Group3", "Group2", "negative", 0.51237, 12, "Group4", "Group5", "positive", 0.14874, 13, "Group4", "Group7", "positive", 0.16683, 14, "Group4", "Group8", "positive", 0.235, 15, "Group4", "Group6", "positive", 0.43237, 16, "Group4", "Group9", "positive", 0.30848, 17, "Group4", "Group1", "positive", 0.0544, 18, "Group4", "Group2", "negative", 0.48404, 22, "Group5", "Group7", "positive", 0.22572, 24, "Group5", "Group6", "positive", 0.1611, 25, "Group5", "Group9", "positive", 0.09827, 26, "Group5", "Group1", "positive", 0.15555, 27, "Group5", "Group2", "negative", 0.27293, 32, "Group7", "Group8", "positive", 0.0736, 33, "Group7", "Group6", "positive", 0.12604, 34, "Group7", "Group9", "positive", 0.13935, 35, "Group7", "Group1", "negative", 0.0994, 42, "Group8", "Group6", "positive", 0.08693, 43, "Group8", "Group9", "positive", 0.23976, 44, "Group8", "Group1", "negative", 0.42419, 45, "Group8", "Group2", "negative", 0.27792, 52, "Group6", "Group9", "positive", 0.1356, 53, "Group6", "Group1", "positive", 0.14775, 54, "Group6", "Group2", "negative", 0.33881, 62, "Group9", "Group1", "negative", 0.07413, 63, "Group9", "Group2", "negative", 0.2427, 72, "Group1", "Group2", "negative", 0.56563 ) # 提取所有唯一节点,按固定顺序排序 all_nodes = links_all %>% select(input, output) %>% pivot_longer(everything(), values_to = "id") %>% distinct(id) %>% arrange(id) %>% pull(id) # 预生成所有中心节点的固定布局 get_fixed_layout = function(center_group) { # 创建包含所有节点的临时图 temp_nodes = tibble(id = all_nodes) temp_edges = links_all %>% filter(input == center_group | output == center_group) %>% rename(from = input, to = output) %>% select(from, to, direction, weight) temp_graph = tbl_graph(nodes = temp_nodes, edges = temp_edges, directed = FALSE) # 生成focus布局,固定中心为目标节点,圆形排列 layout = create_layout(temp_graph, layout = "focus", focus = which(temp_nodes$id == center_group), circular = TRUE) # 保存布局坐标,确保顺序与all_nodes一致 layout %>% arrange(match(id, all_nodes)) %>% select(x, y, id) } # 生成对比用图谱函数 plot_compare_graph = function(current_group) { # 获取固定布局 fixed_layout = get_fixed_layout(current_group) # 筛选当前组的边数据 current_edges = links_all %>% rename(from = input, to = output) %>% filter(from == current_group | to == current_group) %>% mutate(weight_class = as.character(round(weight, 1))) # 标记节点是否在当前网络中 node_data = fixed_layout %>% mutate(in_network = id %in% c(current_edges$from, current_edges$to)) # 设置边宽度映射 weight_levels = unique(current_edges$weight_class) width_values = as.numeric(weight_levels) * 5 names(width_values) = weight_levels # 绘图 set_graph_style() ggraph(node_data, layout = "manual", x = x, y = y) + # 绘制边(仅当前组相关) geom_edge_arc(data = current_edges, aes(x = x, y = y, xend = xend, yend = yend, color = direction, width = weight_class), inherit.aes = FALSE) + # 绘制节点:当前网络节点用彩色,未涉及用灰色半透明 geom_node_point(aes(size = 2, color = ifelse(in_network, id, "uninvolved"), alpha = in_network)) + # 节点标签 geom_node_label(aes(label = id), size = 2, nudge_x = 0.1, nudge_y = 0.1, label.padding = unit(0.25, "lines"), label.r = unit(0.15, "lines"), label.size = 0.25, family = "sans") + # 样式配置 scale_edge_color_manual(values = c("negative" = "#ab0033", "positive" = "#009d4f")) + scale_edge_width_manual(values = width_values) + scale_color_manual(values = c("uninvolved" = "#cccccc", setNames(scales::hue_pal()(length(all_nodes)), all_nodes))) + scale_alpha_manual(values = c(TRUE = 1, FALSE = 0.5)) + guides(alpha = "none", color = guide_legend(title = "Groups")) + labs(title = paste("Centered on", current_group)) } # 生成对比图谱 Group1_plot = plot_compare_graph("Group1") Group1_plot Group7_plot = plot_compare_graph("Group7") Group7_plot
内容的提问来源于stack exchange,提问作者cdjemiel
相关产品推荐
相关产品推荐

