You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 22:10:35