如何在R ggplot中绘制基于p值筛选的暴露-中介-结局三类分类变量关联路径图
暴露-中介-结局分类变量关联可视化实现方案
嘿,针对你要做的流行病学中介效应可视化需求,我整理了一套从数据预处理到代码实现的完整方案,完全贴合你的要求:
一、需求先理清楚
咱们的核心目标是画出4个暴露变量、55个代谢物中介、5个结局变量之间的显著关联(只保留p<0.05的连线),而且只画「暴露阳性→中介阳性」和「中介阳性→结局阳性」的路径,最终要找出哪些代谢物在暴露和结局之间起到了中介作用,参考论文里Figure 4c/5c的样式就行。
二、第一步:数据预处理
首先得把你的stackoverflow数据集里的有效关联挖出来:
- 先逐个检查每个代谢物和4个暴露变量的p值,把p<0.05的「暴露-中介」对挑出来
- 再检查每个代谢物和5个结局变量的p值,把p<0.05的「中介-结局」对挑出来
- 最后只保留那些同时有至少一条暴露关联和一条结局关联的代谢物——毕竟只有这样的代谢物才真正起到中介作用,避免图里出现孤立节点
三、可视化实现:两种主流工具方案
这类路径图用图可视化工具最方便,给你推荐R和Python两种常用方案,按需选就行:
(1)R语言方案(ggraph+tidygraph,颜值高易调整)
这俩包是R里画路径图的黄金组合,能轻松实现分层布局和样式定制:
library(tidygraph) library(ggraph) library(dplyr) library(tidyr) # 1. 提取暴露→中介的显著关联 expo_mediator <- stackoverflow %>% pivot_longer(cols = starts_with("exposure"), names_to = "exposure", values_to = "p_val") %>% filter(p_val < 0.05) %>% mutate(from = gsub("_p", "", exposure), to = metabolite, type = "暴露→中介") # 2. 提取中介→结局的显著关联 mediator_outcome <- stackoverflow %>% pivot_longer(cols = starts_with("outcome"), names_to = "outcome", values_to = "p_val") %>% filter(p_val < 0.05) %>% mutate(from = metabolite, to = gsub("_p", "", outcome), type = "中介→结局") # 3. 合并边数据,构建图对象 graph_data <- bind_rows(expo_mediator, mediator_outcome) %>% as_tbl_graph(directed = TRUE) # 4. 给节点分组(暴露/中介/结局) graph_data <- graph_data %>% activate(nodes) %>% mutate(group = case_when( grepl("exposure", name) ~ "暴露变量", grepl("outcome", name) ~ "结局变量", TRUE ~ "中介代谢物" )) # 5. 绘制分层路径图 ggraph(graph_data, layout = "linear", circular = FALSE) + geom_edge_link(aes(color = type), arrow = arrow(length = unit(2, 'mm')), alpha = 0.7) + geom_node_point(aes(color = group, size = ifelse(group == "中介代谢物", 3, 5))) + geom_node_text(aes(label = name), repel = TRUE, size = 3, hjust = 0.5) + scale_color_manual(values = c("暴露变量" = "#2E86AB", "中介代谢物" = "#F24C4E", "结局变量" = "#F7D060")) + theme_graph(base_family = "sans") + labs(title = "暴露-中介-结局显著关联路径图", color = "关联类型")
(2)Python方案(networkx+matplotlib,Python用户友好)
如果平时用Python更多,用这俩包也能轻松实现:
import pandas as pd import networkx as nx import matplotlib.pyplot as plt # 假设你的数据已经加载为DataFrame df = pd.read_csv("your_dataset.csv") # 初始化有向图 G = nx.DiGraph() # 添加暴露→中介的边 for _, row in df.iterrows(): metab = row['metabolite'] # 遍历4个暴露变量 for expo_col in ['exposure1_p', 'exposure2_p', 'exposure3_p', 'exposure4_p']: if row[expo_col] < 0.05: expo_name = expo_col.replace("_p", "") G.add_edge(expo_name, metab) # 添加中介→结局的边 for _, row in df.iterrows(): metab = row['metabolite'] # 遍历5个结局变量 for outcome_col in ['outcome1_p', 'outcome2_p', 'outcome3_p', 'outcome4_p', 'outcome5_p']: if row[outcome_col] < 0.05: outcome_name = outcome_col.replace("_p", "") G.add_edge(metab, outcome_name) # 设置分层布局:暴露左、中介中、结局右 pos = {} # 暴露节点位置 expo_nodes = [n for n in G.nodes if 'exposure' in n] pos.update((node, (0, i)) for i, node in enumerate(expo_nodes)) # 结局节点位置 outcome_nodes = [n for n in G.nodes if 'outcome' in n] pos.update((node, (2, i)) for i, node in enumerate(outcome_nodes)) # 中介节点位置 mediator_nodes = [n for n in G.nodes if n not in expo_nodes + outcome_nodes] pos.update((node, (1, i)) for i, node in enumerate(mediator_nodes)) # 绘制图形 plt.figure(figsize=(14, 10)) # 画边 nx.draw_networkx_edges(G, pos, arrowstyle='->', arrowsize=12, edge_color='#666666', alpha=0.7) # 画节点,按类型区分颜色 nx.draw_networkx_nodes(G, pos, nodelist=expo_nodes, node_color='#2E86AB', node_size=1500) nx.draw_networkx_nodes(G, pos, nodelist=outcome_nodes, node_color='#F7D060', node_size=1500) nx.draw_networkx_nodes(G, pos, nodelist=mediator_nodes, node_color='#F24C4E', node_size=1000) # 加标签 nx.draw_networkx_labels(G, pos, font_size=10, font_family='sans-serif') plt.title("暴露-中介-结局显著关联路径图", fontsize=16, pad=20) plt.box(False) plt.show()
四、小Tips让图更专业
- 因为中介变量有55个,建议只保留同时关联暴露和结局的代谢物,不然图会挤成一团,没法看
- 可以把连线的粗细和p值挂钩(p越小线越粗),能更直观展示关联强度
- 如果想更贴近论文里的样式,可以调整节点颜色、字体大小,或者给不同分组的节点加边框
内容的提问来源于stack exchange,提问作者ehepikait
相关产品推荐
相关产品推荐

