如何在Alluvial/Sankey图中设置Y轴为百分比刻度?
解决ggplot2冲积图Y轴百分比刻度问题
我来帮你搞定这个Y轴百分比设置的问题~
问题根源
你遇到的核心问题是:冲积图的Y轴原始数值是类别频数(比如某个分组有14个样本,Y轴就显示14),直接用scales::percent()会把这个频数当成比例值(比如14变成1400%),完全不符合你的需求。我们需要把频数转换成「占该时间点总样本数的百分比」,同时保证刻度正好是0%、10%…100%。
解决方案
你的数据里每个time组都有20个样本(time=1和time=2各20行),所以我们可以基于这个总样本数来转换Y轴的显示标签:
- 先定义每个时间点的总样本数:
n <- 20 - 在
scale_y_continuous里做两个关键设置:breaks:设置为频数对应的10%间隔点(0、2、4…20,分别对应0%、10%…100%)labels:用自定义函数把频数转换成百分比(比如2→10%,20→100%)
完整可运行代码
library(ggplot2) library(ggalluvial) # 必须加载这个包才能用geom_flow/geom_stratum library(scales) # 你的数据集 PIPPO <- data.frame( "ID"=rep(c(1:20),2), "time"=c(rep(1,20),rep(2,20)), "value"=c("B","G","B","G","B",rep("G",3),rep("B",2),"G",rep("B",3),"G",rep("B",6),"G","B","G","B",rep("G",3),rep("B",2),"G",rep("B",3),"G","B","switch",rep("B",2),"switch") ) n <- 20 # 每个time组的总样本数 ggplot(PIPPO, aes(x = time, stratum = value, alluvium = ID, fill = value, label = value)) + scale_fill_brewer(type = "qual", palette = "Set3") + geom_flow(stat = "flow", knot.pos = 1/4, aes.flow = "forward", color = "gray") + geom_stratum() + theme(legend.position = "bottom") + scale_y_continuous( breaks = seq(0, n, by = n*0.1), # 对应10%间隔的频数位置 labels = function(x) percent(x/n), # 将频数转为百分比标签 limits = c(0, n) # 锁定Y轴范围为0到总样本数,对应0%到100% )
为什么这个方法有效
这样设置后,Y轴的底层计算还是用原始频数(保证冲积图的高度、流向完全正确),但显示给你的是百分比标签,而且刻度严格按照每10%的间隔排列,完美匹配你的需求。
如果你的数据中不同time组的样本数不一样,可以先用dplyr分组计算每个time的总样本数,再动态映射到Y轴设置里——不过你的当前数据是固定20个样本,所以直接用n=20就足够啦。
内容的提问来源于stack exchange,提问作者jeff
相关产品推荐
相关产品推荐

