如何使用ggplot绘制按分组百分比统计的直方图
实现分队列组内归一化的绘图方案
原有代码的问题
你使用的y = stat(density)无法达到预期效果:stat(density)返回的是全局核密度估计值,且直方图的密度计算逻辑不匹配你需要的「每个队列内各得分频数占比之和为1」的需求。
推荐实现方式
因为你的Depression得分是1-4的离散值,优先选择geom_col/geom_bar而非直方图实现,两种可行方案如下:
方案1:提前统计占比(逻辑清晰,易调试)
先按队列分组计算每个得分的占比,再绘图:
library(tidyverse) # 示例数据 d <- structure(list(Cohort = c("Fall", "Spring", "Summer", "Fall", "Spring", "Summer", "Fall", "Spring", "Summer", "Fall", "Spring", "Summer", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall", "Summer", "Fall", "Spring", "Summer", "Fall", "Spring", "Summer", "Fall", "Spring", "Summer", "Spring", "Spring", "Fall", "Fall", "Fall", "Fall", "Fall", "Fall"), Depression = c(1, 2, 2, 4, 2, 1, 1, 3, 2, 3, 2, 4, 2, 2, 4, 2, 1, 1, 3, 1, 3, 2, 4, 3, 3, 2, 4, 2, 1, 1, 3, 2, 3, 2, 4, 1, 4, 1, 1, 3, 4, 1, 1)), row.names = c(NA, -43L), class = c("tbl_df", "tbl", "data.frame")) # 分组统计占比 d_stats <- d %>% count(Cohort, Depression) %>% group_by(Cohort) %>% mutate(pct = n / sum(n)) %>% ungroup() # 绘图 ggplot(d_stats, aes(x = factor(Depression), y = pct, fill = Cohort)) + geom_col(position = position_dodge(0.9), width = 0.8) + scale_y_continuous(labels = scales::percent(), limits = c(0, NA)) + labs(x = "Depression得分", y = "队列内占比") + theme_minimal()
方案2:直接在ggplot层计算(无需预处理数据)
如果不想提前做数据汇总,可以通过after_stat实现实时分组计算:
ggplot(d, aes(x = factor(Depression), fill = Cohort)) + geom_bar( aes(y = after_stat(count / ave(count, group, FUN = sum))), position = position_dodge(0.9) ) + scale_y_continuous(labels = scales::percent(), limits = c(0, NA)) + labs(x = "Depression得分", y = "队列内占比") + theme_minimal()
两种方案都可以保证每个队列对应的4个柱子的占比之和为1,不受队列样本量差异的影响。
内容的提问来源于stack exchange,提问作者a_todd12
相关产品推荐
相关产品推荐

