在R语言中绘制多阶段节点标签相同的桑基图
桑基图绘制修正方案:年份间风险等级迁移可视化
原代码核心问题
- 数据转换逻辑错误:
pivot_stages_longer需要的是每个观测(ID)在各阶段(年份)的状态数据,而非先聚合后的比例数据。原代码提前聚合各年份风险等级占比,导致无法捕捉个体迁移路径,桑基图流量关系混乱。 - 绘图映射参数错误:
geom_sankeyedge和geom_sankeynode参数匹配不当,缺少必要的流量映射,且v_space设置未配合数据调整。
修正后的完整代码
library(ggsankeyfier) library(dplyr) library(ggplot2) library(tidyr) # 原始数据 df <- data.frame( ID = c(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5), risk_level = c("High", "High", "High", "Low", "Low", "Very low", "Low", "Low", "Low", "Low", "Moderate", "Low", "Moderate", "High", "High"), Year = c(2022, 2023, 2024, 2022, 2023, 2024, 2022, 2023, 2024, 2022, 2023, 2024, 2022, 2023, 2024)) # 步骤1:转换为宽格式(每个ID一行,列对应各年份的风险等级) df_wide <- df %>% pivot_wider(names_from = Year, values_from = risk_level) # 步骤2:转换为桑基图所需的长格式 df_sankey <- pivot_stages_longer( df_wide, stages_from = c("2022", "2023", "2024"), # 指定阶段(年份)列 values_to = "risk_level", # 状态列名 id_cols = ID # 观测ID列 ) # 步骤3:计算各迁移路径的比例(按起始年份分组) df_sankey <- df_sankey %>% group_by(stage, node) %>% summarise(count = n(), .groups = "drop") %>% group_by(stage) %>% mutate(proportion = count / sum(count)) %>% ungroup() # 步骤4:绘制桑基图 ggplot(df_sankey, aes(x = stage, y = proportion, group = node, connector = connector, edge_id = edge_id, fill = node)) + geom_sankeyedge(color = "white", alpha = 0.7) + # 流量边样式 geom_sankeynode(color = "black", size = 0.2) + # 节点样式 scale_fill_viridis_d(option = "plasma") + # 配色调整 labs(x = "年份", y = "占比", fill = "风险等级") + theme_minimal() + theme(axis.text.x = element_text(size = 12), legend.position = "bottom")
关键说明
- 先转宽格式是让
pivot_stages_longer正确识别每个ID的跨年份状态迁移,这是桑基图捕捉路径的核心。 - 比例计算放在格式转换后,确保每个迁移路径的占比基于对应年份的总观测数。
- 调整边和节点样式、添加中文标签,让图表更贴合需求。
内容的提问来源于stack exchange,提问作者ccc
相关产品推荐
相关产品推荐

