如何在ggplot2分组柱状图中显示各性别分组的单独计数标签
问题描述
想要绘制不同年龄组中男性(Male)与女性(Female)的分组柱状图,期望在对应颜色的柱子上显示男女各自的计数,但当前图表仅展示了各年龄组的总计数。现提供示例数据及所用R语言tidyverse包的ggplot2代码,咨询如何实现按年龄组在男女各自的柱子上显示单独的计数标签。
示例数据
| Age | sex | AgeGroup |
|---|---|---|
| 22 | F | 18-25 Years |
| 36 | F | 36-45 Years |
| 20 | M | 18-25 Years |
现有代码
library(tidyverse) ggplot(demo_df, mapping = aes(x = AgeGroup)) + geom_bar(aes(fill = sex), position="dodge")+ geom_text(stat = "count", aes(label = scales::comma(after_stat(count))), nudge_y = 10000, fontface = 2) + theme_minimal() + theme(axis.text.x = element_text(angle = 90, hjust = 0), axis.text.y.left = element_blank(), axis.title.y.left = element_blank())
解决方法
问题核心是geom_text未按性别拆分计数,也没和柱子做位置对齐,导致标签默认展示了年龄组总计数。只需两处关键修改即可解决:
- 给
geom_text的aes添加group = sex(或fill = sex,与geom_bar保持一致),让ggplot识别需要按性别拆分统计; - 设置
position = position_dodge(width = 0.9),使标签与对应柱子对齐(0.9是geom_bar默认的分组宽度,匹配后标签不会偏移); - 调整
nudge_y数值:示例数据中计数都很小,原代码的10000会把标签推到极远处,改成0.1这类小数值更合理。
修改后的代码(基于stat="count")
library(tidyverse) ggplot(demo_df, mapping = aes(x = AgeGroup)) + geom_bar(aes(fill = sex), position = "dodge") + geom_text( stat = "count", aes(label = scales::comma(after_stat(count)), group = sex), position = position_dodge(width = 0.9), nudge_y = 0.1, fontface = 2 ) + theme_minimal() + theme( axis.text.x = element_text(angle = 90, hjust = 0), axis.text.y.left = element_blank(), axis.title.y.left = element_blank() )
可选方案:先汇总数据再绘图
如果觉得依赖stat="count"不够直观,也可以先用dplyr提前汇总计数,再绘制图表,逻辑更清晰:
# 提前汇总各年龄组、性别的计数 summary_df <- demo_df %>% count(AgeGroup, sex) ggplot(summary_df, aes(x = AgeGroup, y = n, fill = sex)) + geom_col(position = "dodge") + geom_text( aes(label = scales::comma(n)), position = position_dodge(width = 0.9), nudge_y = 0.1, fontface = 2 ) + theme_minimal() + theme( axis.text.x = element_text(angle = 90, hjust = 0), axis.text.y.left = element_blank(), axis.title.y.left = element_blank() )
两种方法都能实现每个性别柱子上显示单独的计数标签。
内容的提问来源于stack exchange,提问作者Usman YousafZai
相关产品推荐
相关产品推荐

