ggplot2绘制柱状图如何将各组样本量标注放在X轴标签下方
ggplot2 分组柱状图X轴分组名下方添加样本量标注实现方案
stat_n_text() 仅支持在绘图区域内部放置标注,原生不支持将文本放到绘图区外的轴标签区域,不需要硬改这个函数的参数,以下两个方案都可以实现需求,优先推荐第一个,稳定性最高。
方案1:自定义X轴刻度标签(适配分面场景,无错位问题)
核心逻辑是提前统计各分组样本量,直接把样本量文本整合到X轴刻度标签里,通过换行符放到分组名下方,不需要处理绘图区裁剪、位置偏移的问题,适配当前的facet_wrap分面和自由轴尺度设置。
- 加载dplyr做分组统计,生成带样本量的轴标签文本:
library(dplyr) # 按分面变量、X轴分组变量统计样本量 axis_label_data <- data %>% group_by(parameter, group) %>% summarise(sample_n = n(), .groups = "drop") %>% mutate(label_text = paste0(group, "\n(n=", sample_n, ")"))
- 修改原绘图代码,替换X轴标签,同时给底部预留足够的显示空间:
ggplot(data, aes(group, pm_l, fill=condition)) + theme_classic() + geom_bar(position = position_dodge(), stat = "identity") + facet_wrap(~parameter, scales = "free") + ylab("pm_l") + scale_fill_brewer(palette = "Paired") + # 绑定分组和对应的带样本量标签 scale_x_discrete( labels = setNames(axis_label_data$label_text, axis_label_data$group) ) + # 调整底部边距,避免标签被截断,微调X轴文本垂直对齐方式 theme( plot.margin = margin(b = 12), axis.text.x = element_text(vjust = 1) )
这个方案下样本量标注和分组名永远对齐,不会因为柱状图位置调整、分面轴范围变化出现错位。
方案2:独立文本层标注到轴外侧
如果需要保留原有X轴分组名的样式,单独把样本量标注放在分组名更靠下的位置,可以用geom_text手动放置标注,注意关闭坐标裁剪允许绘图区外的内容显示:
- 统计样本量的步骤和方案1一致,只需要把标签文本改成
n=X格式即可:
n_label_data <- data %>% group_by(parameter, group) %>% summarise(sample_n = n(), .groups = "drop") %>% mutate(label_text = paste0("n=", sample_n))
- 绘图时添加独立文本层,关闭坐标裁剪:
ggplot(data, aes(group, pm_l, fill=condition)) + theme_classic() + geom_bar(position = position_dodge(), stat = "identity") + facet_wrap(~parameter, scales = "free") + ylab("pm_l") + scale_fill_brewer(palette = "Paired") + # 放置样本量标注,y设为-Inf对齐轴的最底部 geom_text( data = n_label_data, aes(x = group, y = -Inf, label = label_text), vjust = 2, size = 3, inherit.aes = FALSE ) + # 关闭坐标裁剪,允许显示绘图区外的文本 coord_cartesian(clip = "off") + # 加大底部边距给标注留空间 theme(plot.margin = margin(b = 20))
这个方案需要根据实际的图尺寸、y轴范围微调vjust参数,避免标注和原有X轴标签重叠,稳定性弱于方案1。
注:
stat_n_text()本身定位就是绘图区内的统计值标注,就算强行设置负y值,也会被ggplot默认的坐标裁剪拦截,分面自由轴场景下不同分面的y轴范围不一致,很容易出现标注位置高低不齐的问题,不建议用这个函数强行实现轴外标注。
内容的提问来源于stack exchange,提问作者Carmen O
相关产品推荐
相关产品推荐

