如何在ggplot2堆叠柱状图上方正确添加带“n=”的样本量标签?
堆叠柱状图样本量标签定位与格式化问题
实验背景
在本实验中,我们追踪受试动物是否存在细菌感染,分离出感染动物体内的细菌类型后,使用ggplot2绘制堆叠柱状图(position='stack',stat='identity')。该图表X轴为“实验开始后周数”,Y轴为“细菌感染阳性动物比例”。
原始代码与问题
以下为示例数据集及对应的ggplot2代码:
DummyData <- data.frame(matrix(ncol = 5, nrow = 78)) colnames(DummyData) <- c('WeeksSinceStart','BacteriaType','PositiveOccurences','SampleSize','NewSampleSize') DummyData$WeeksSinceStart <- c(1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,9,9,9,9,9,10,10,10,10) DummyData$BacteriaType <- c("BactA","BactB","BactD","BactB","BactE","BactA","BactS","BactF","BactE","BactH","BactJ","BactK","BactE","BactB","BactS","BactF","BactL","BactE","BactW","BactH","BactS","BactJ","BactQ","BactN","BactW","BactA","BactD","BactE","BactA","BactC","BactD","BactK","BactL","BactE","BactD","BactA","BactS","BactK","BactB","BactE","BactF","BactH","BactN","BactE","BactL","BactZ","BactE","BactC","BactR","BactD","BactJ","BactN","BactK","BactW","BactR","BactE","BactW","BactA","BactM","BactG","BactO","BactI","BactE","BactD","BactM","BactH","BactC","BactM","BactW","BactA","BactL","BactB","BactE","BactA","BactS","BactH","BactQ","BactF") PosOcc <- seq(from = 1, to = 2, by = 1) DummyData$PositiveOccurences <- rep(PosOcc, times = 13) DummyData$SampleSize <- c(78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,78,29,29,29,29,29,10,10,10,10) DummyData$NewSampleSize <- c(78,NA,NA,NA,NA,NA,NA,NA,NA,78,NA,NA,NA,NA,NA,NA,NA,NA,78,NA,NA,NA,NA,NA,NA,NA,78,NA,NA,NA,NA,NA,NA,NA,NA,78,NA,NA,NA,NA,NA,NA,NA,NA,NA,78,NA,NA,NA,NA,NA,NA,NA,78,NA,NA,NA,NA,NA,NA,NA,NA,78,NA,NA,NA,NA,NA,NA,29,NA,NA,NA,NA,10,NA,NA,NA) numcolor <- 20 plotcolors <- colorRampPalette(brewer.pal(8, "Set3"))(numcolor) #GGplot for Dummy Data DummyDataPlot <- ggplot(DummyData, aes(x = WeeksSinceStart, y = PositiveOccurences/SampleSize, fill = BacteriaType)) + geom_bar(position = "stack", stat = "identity") + geom_text(label = DummyData$NewSampleSize, nudge_y = 0.1) + scale_y_continuous(limits = c(0,0.6), breaks = seq(0, 1, by = 0.1)) + scale_x_continuous(limits = c(0.5,11), breaks = seq(0,10, by =1)) + labs( x = "Weeks Since Start", y = "Proportion Positive") + scale_fill_manual(values = plotcolors)
遇到的问题
- 无法将
geom_text生成的样本量标签准确定位在每个柱状图的正上方 - 希望在样本量值前添加文本“n = ”
尝试过调整position_dodge参数和nudge_y参数,但均未成功。
解决方案
核心思路是先计算每周堆叠柱状图的总高度(即总阳性比例),再基于该高度放置格式化后的标签,具体步骤如下:
步骤1:预处理数据,计算总高度并格式化标签
使用dplyr分组汇总每周的总阳性比例,提取有效样本量并添加“n = ”前缀:
library(dplyr) library(ggplot2) library(RColorBrewer) # 预处理标签数据 label_data <- DummyData %>% group_by(WeeksSinceStart) %>% summarise( total_prop = sum(PositiveOccurences/SampleSize, na.rm = TRUE), sample_size = first(na.omit(NewSampleSize)) ) %>% mutate(label_text = paste0("n = ", sample_size))
步骤2:修改ggplot代码,精准定位标签
调用预处理后的标签数据,将标签Y轴位置设为每周总阳性比例,再微调位置确保在柱状图顶部:
numcolor <- 20 plotcolors <- colorRampPalette(brewer.pal(8, "Set3"))(numcolor) DummyDataPlot <- ggplot(DummyData, aes(x = WeeksSinceStart, y = PositiveOccurences/SampleSize, fill = BacteriaType)) + geom_bar(position = "stack", stat = "identity") + # 添加格式化后的样本量标签 geom_text(data = label_data, aes(x = WeeksSinceStart, y = total_prop, label = label_text), inherit.aes = FALSE, nudge_y = 0.02, size = 4) + scale_y_continuous(limits = c(0, 0.6), breaks = seq(0, 1, by = 0.1)) + scale_x_continuous(limits = c(0.5, 11), breaks = seq(0, 10, by = 1)) + labs( x = "Weeks Since Start", y = "Proportion Positive" ) + scale_fill_manual(values = plotcolors) # 查看最终图表 DummyDataPlot
关键说明
inherit.aes = FALSE:避免继承主图层的填充色映射,简化标签图层的美学设置nudge_y = 0.02:根据Y轴刻度范围微调标签位置,确保不与柱状图顶部重叠- 通过分组汇总计算总高度,从根源上保证标签位置与柱状图顶部对齐
内容的提问来源于stack exchange,提问作者ruser123
相关产品推荐
相关产品推荐

