为含多响应变量的比例堆叠柱状图添加顶部总计
问题:为堆叠比例柱状图添加总计失败,计数版本可正常显示(含警告)
尝试为x、y均为多响应变量的堆叠比例柱状图添加总计,计数版本的图表虽有警告但成功添加了总计,然而比例版本的图表添加总计完全失败。
数据集片段
structure(list(HNV_grasslands = c(1L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), HNV_arable = c(1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L), HNV_permanent_crop = c(1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L), HNV_mosaic = c(1L, 0L, 1L, 0L, 0L, 0L, 1L, 1L, 1L, 0L, 1L), Animal_vegetal = c("", "Both", "Both", "Both", "", "Vegetal species", "Vegetal species", "", "Both", "Animal species", "Both")), row.names = 10:20, class = "data.frame")
计数版本代码(含警告但可显示总计)
警告信息
The following aesthetics were dropped during statistical transformation: fill This can happen when ggplot fails to infer the correct grouping structure in the data. Did you forget to specify a
groupaesthetic or to convert a numerical variable into a factor?
代码
hnvf4 <- hnvf3 %>% pivot_longer( cols = starts_with("HNV"), names_to = c("HNV"), names_prefix = "HNV_", values_to = "value1") |> filter(value1 == 1 & Animal_vegetal !="") |> select(-value1) # 移除value1,避免数据全为1的情况 glimpse(hnvf4) hnvf4 |> ggplot(aes(x = HNV,fill = factor(Animal_vegetal, levels=c("Animal species", "Vegetal species", "Both")))) + geom_bar()+ geom_text(stat ="count",aes(label=after_stat(count), group= HNV, vjust= -1))+ scale_fill_manual(values = c("#FDCDAC", "#B3E2CD","#CBD5E8"))+ theme(axis.text.x = element_text(angle=90, vjust = 0.5, hjust=1), axis.ticks.x = element_blank())+ theme(axis.line.y = element_line(linewidth = 0.5, colour = "black"), axis.ticks.length.y.left = unit(.25, "cm"))+ theme(panel.background = element_rect(fill=NA))+ scale_x_discrete(labels=c('arable land', 'grasslands', 'mosaic landscape', 'permanent croplands')) + labs(x= "HNV farmland type", y="Number of studies", fill= "")+ theme(axis.title.y = element_text(margin=margin(r= 15)))+ scale_y_continuous(limits= c(0,100), breaks=c(0,25,50,75, 100),expand = c(0,0)) + theme(legend.position = c(.99, .95), legend.justification = c("right", "top"))
比例版本代码(无法添加总计)
hnvf4%>% ggplot(aes(x = HNV,fill = factor(Animal_vegetal,levels=c("Animal species", "Vegetal species", "Both")))) + geom_bar(position="fill")+ #geom_text(stat ="count",aes(label=after_stat(count), group= HNV, vjust= -1))+ scale_fill_manual(values = c("#FDCDAC", "#B3E2CD","#CBD5E8"))+ theme(axis.text.x = element_text(angle=90, vjust = 0.5, hjust=1), axis.ticks.x = element_blank())+ theme(axis.line.y = element_line(linewidth = 0.5, colour = "black"), axis.ticks.length.y.left = unit(.25, "cm"))+ theme(panel.background = element_rect(fill=NA))+ scale_x_discrete(labels=c('arable land', 'grasslands', 'mosaic landscape', 'permanent croplands')) + labs(x= "HNV farmland type", y="Proportion of studies", fill= "")+ theme(axis.title.y = element_text(margin=margin(r= 15)))+ # 移除y轴额外空白,让y轴从0开始 scale_y_continuous(expand = c(0,0))
解决方案
比例版本的核心问题在于position="fill"将y轴转换为0-1的比例区间,直接使用stat="count"会因分组和坐标映射冲突导致总计无法正确显示。最稳妥的方式是提前计算每个HNV类别的总计数,再将总计文本映射到比例轴上方:
步骤1:计算总计数
# 统计每个HNV类型的有效样本总数 total_counts <- hnvf4 %>% group_by(HNV) %>% summarise(total = n(), .groups = "drop")
步骤2:修改比例图表代码,添加总计
hnvf4 %>% ggplot(aes(x = HNV, fill = factor(Animal_vegetal, levels=c("Animal species", "Vegetal species", "Both")))) + geom_bar(position="fill") + # 添加总计文本,使用提前计算的总计数数据集 geom_text(data = total_counts, aes(x = HNV, y = 1.05, label = total, fill = NULL), size = 3.5, vjust = 0) + scale_fill_manual(values = c("#FDCDAC", "#B3E2CD","#CBD5E8")) + theme(axis.text.x = element_text(angle=90, vjust = 0.5, hjust=1), axis.ticks.x = element_blank()) + theme(axis.line.y = element_line(linewidth = 0.5, colour = "black"), axis.ticks.length.y.left = unit(.25, "cm")) + theme(panel.background = element_rect(fill=NA)) + scale_x_discrete(labels=c('arable land', 'grasslands', 'mosaic landscape', 'permanent croplands')) + labs(x= "HNV farmland type", y="Proportion of studies", fill= "") + theme(axis.title.y = element_text(margin=margin(r= 15))) + # 扩展y轴上限,确保总计文本能完整显示 scale_y_continuous(expand = c(0,0), limits = c(0, 1.1)) + theme(legend.position = c(.99, .95), legend.justification = c("right", "top"))
说明
- 提前计算总计数可以避免ggplot统计变换时的分组歧义,确保总计数值准确。
- 将
y=1.05设置在比例轴(0-1)上方,配合scale_y_continuous(limits = c(0, 1.1))扩展y轴范围,保证总计文本不被截断。 - 设置
fill = NULL避免继承主图的fill美学,防止出现不必要的分组警告。
内容的提问来源于stack exchange,提问作者elsich
相关产品推荐
相关产品推荐

