如何在分组冲积图中展示各时间点分层的百分比占比
问题描述
用户拥有一项包含4个实验组(Group)、3个测量时间点(Time)的干预研究数据,已完成剖面与转换分析得到4个剖面(Profile),并使用以下R代码绘制了展示各实验组不同时间点剖面转换的冲积图:
library(ggplot2) library(ggalluvial) library(dplyr) library(tidyr) df <- tibble(id = 1:400, group = sample(1:4, size = 400, replace = TRUE)) |> crossing(time = 1:3) |> mutate(profile = sample(1:4, size = n(), replace = TRUE))|> mutate(profile = as.character(profile), time = as.character(time)) ggplot(df, aes(x = time, stratum = profile, alluvium = id, fill = profile, label = profile)) + scale_fill_brewer(type = "seq", palette = "BrBG") + geom_flow() + geom_stratum() + labs(x = "Time", y = "N") + facet_wrap('group', labeller = label_both)
由于4个实验组样本量不同,希望将冲积图中的分层尺寸由绝对数值改为相对百分比,使每个时间点的所有剖面占比总和为100%,尝试使用weight属性未成功,寻求可行的实现方法。
解决方案
要实现按百分比展示的冲积图,核心是先计算每个分组、时间点下各剖面的相对占比,再结合ggalluvial的统计层映射权重,以下是两种可行实现方式:
方式一:基于汇总数据绘制(更高效)
先统计各组各时间点的剖面占比,再用汇总数据绘图:
- 计算百分比权重
df_summary <- df |> group_by(group, time, profile) |> summarise(count = n(), .groups = "drop") |> group_by(group, time) |> mutate(percent = count / sum(count)) |> ungroup()
- 绘制百分比冲积图
ggplot(df_summary, aes(x = time, stratum = profile, alluvium = profile, fill = profile, label = profile, weight = percent)) + scale_fill_brewer(type = "seq", palette = "BrBG") + geom_flow(stat = "alluvium", lode.guidance = "rightleft") + geom_stratum() + # 给分层添加百分比标签 geom_text(stat = "stratum", aes(label = paste0(round(percent*100), "%"))) + labs(x = "Time", y = "Percentage (%)") + facet_wrap('group', labeller = label_both) + scale_y_continuous(labels = scales::percent_format())
方式二:基于原始数据保留个体轨迹
若需要保留每个个体的转换轨迹,可在原始数据中为每个样本分配对应权重:
- 添加权重列
df_weighted <- df |> group_by(group, time) |> mutate(weight = 1 / n()) |> ungroup()
- 绘制带个体轨迹的百分比冲积图
ggplot(df_weighted, aes(x = time, stratum = profile, alluvium = id, fill = profile, label = profile, weight = weight)) + scale_fill_brewer(type = "seq", palette = "BrBG") + geom_flow() + geom_stratum() + labs(x = "Time", y = "Percentage (%)") + facet_wrap('group', labeller = label_both) + scale_y_continuous(labels = scales::percent_format())
关键说明
- 两种方式的核心都是通过
weight参数映射相对占比,让每个时间点的分层总和为100%; scale_y_continuous配合scales::percent_format()将y轴转为百分比刻度,提升可读性;- 方式一适合仅关注剖面转换占比的场景,计算效率更高;方式二则保留了个体级别的流动细节。
内容的提问来源于stack exchange,提问作者user30330533
相关产品推荐
相关产品推荐

