如何在ggalluvial中实现多流汇聚至同一节点分区的桑基图绘制?
用ggalluvial实现多流汇聚到同一节点分区的方法
要让多个上游节点的流汇聚到下游同一个节点分区,核心是利用ggalluvial中alluvium参数的“轨迹跟踪”特性——它用来标识每一条流动的“实体/分组”,只要把需要合并的流归到同一个alluvium分组,或者让不同上游实体的下游轨迹指向同一个目标分区,就能实现汇聚效果。下面我分两种场景给你具体代码和解释:
场景1:基于个体级数据的汇聚(最直观)
如果你的数据是每个样本(比如用户、受试者)的时间序列记录,直接修改样本在下游节点的分类即可:
library(ggalluvial) set.seed(123) # 固定随机数保证结果一致 # 构造模拟数据:50个受试者的3次调查响应 # Time1:20人选always,15人选sometimes,15人选never time1 <- data.frame( survey = "Time1", subject = 1:50, response = c(rep("always",20), rep("sometimes",15), rep("never",15)), freq = 1 ) # Time2:让Time1的always和sometimes全部转为always,never保持不变 time2 <- data.frame( survey = "Time2", subject = 1:50, response = c(rep("always",35), rep("never",15)), freq = 1 ) # Time3:保持Time2的响应结果 time3 <- data.frame( survey = "Time3", subject = 1:50, response = c(rep("always",35), rep("never",15)), freq = 1 ) # 合并数据并整理因子顺序 combined_data <- rbind(time1, time2, time3) combined_data$response <- factor(combined_data$response, levels = c("always", "sometimes", "never")) # 绘制桑基图 ggplot(combined_data, aes( x = survey, stratum = response, alluvium = subject, # 用subject跟踪每个个体的流动轨迹 y = freq, fill = response, label = response )) + scale_x_discrete(expand = c(.1, .1)) + geom_flow() + # 流会自动汇聚到对应的下游分区 geom_stratum(alpha = .5) + geom_text(stat = "stratum", size = 3) + theme(legend.position = "right") + ggtitle("多流汇聚效果:Time1的always+sometimes → Time2的always")
运行后你会看到:Time1的always和sometimes两条流,全部汇聚到Time2的always节点分区里,完美实现你要的效果。
场景2:基于汇总数据的汇聚(适合大样本)
如果你的数据已经是汇总后的频率值,不需要个体记录,可以手动指定alluvium分组来关联需要合并的流:
library(ggalluvial) library(dplyr) # 构造汇总数据:注意下游节点的频率是上游流入频率之和 summary_data <- data.frame( survey = rep(c("Time1", "Time2", "Time3"), each = 3), response = rep(c("always", "sometimes", "never"), 3), freq = c(20,15,15, 35,0,15, 35,0,15) # Time2的always=20+15=35 ) # 关键:给需要合并的流指定同一个alluvium分组 summary_data <- summary_data %>% mutate(alluvium = case_when( # Time1的always和sometimes都归为group1,对应下游的always (survey == "Time1" & response %in% c("always", "sometimes")) | (survey %in% c("Time2","Time3") & response == "always") ~ "group1", # never的流单独归为group2 survey %in% c("Time1","Time2","Time3") & response == "never" ~ "group2", TRUE ~ NA_character_ )) # 绘图 ggplot(summary_data, aes( x = survey, stratum = response, alluvium = alluvium, # 用分组标识跟踪流的汇聚 y = freq, fill = response, label = response )) + scale_x_discrete(expand = c(.1, .1)) + geom_flow() + geom_stratum(alpha = .5) + geom_text(stat = "stratum", size = 3) + theme(legend.position = "right") + ggtitle("汇总版多流汇聚桑基图")
核心原理总结
alluvium是关键:它相当于每条流的“身份证”,只要两个上游流的alluvium在下游指向同一个stratum(分区),它们就会自动汇聚。- 频率要匹配:下游目标分区的频率必须等于所有流入它的上游分区频率之和,否则节点块大小会出现断层。
- 两种场景任选:个体级数据更直观,汇总级数据更高效,根据你的原始数据类型选择即可。
内容的提问来源于stack exchange,提问作者userq8957289475
相关产品推荐
相关产品推荐

