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

如何绘制带填充分组的百分比分面直方图?

问题描述

我想要绘制一个带有分面和填充分组变量的百分比直方图。此前相关讨论未涉及填充分组变量,使用density的解决方案结果异常:代码中第一条geom_histogram语句生成的R分组线条不正确,第二条则生成正常计数。如何输出正确的分面百分比?

附带代码:

values <- sample(c(4,8,16,32,64,128,256,512),1000,replace=TRUE)
groups <- sample(c("A","B","C","D"),1000,replace=TRUE)
daf <- data.frame(group=groups,value=values)
daf$state <- "S"
daf$state[daf$group == "A" & daf$value > 16] <- "R"
daf$state[daf$group == "B" & daf$value > 64] <- "R"
daf$state[daf$group == "C" & daf$value > 32] <- "R"
daf$state[daf$group == "D" & daf$value > 256] <- "R"

p <- ggplot(daf, aes(x=value,fill=state)) +
 geom_histogram(aes(y = stat(density)*0.5),binwidth=0.5) +
  # geom_histogram(aes(y = stat(count)),binwidth=0.5) +
  scale_x_continuous(name = "log2-trans",trans="log2",labels = scales::math_format(2^.x, format = log2),breaks = c(0.015625,0.03125,0.0625,0.125,0.25,0.5,0,1,2,4,8,16,32,64,128,256,512)) +
  scale_y_continuous(name = "Count")+
  facet_wrap(~ group,nrow=5,ncol=3,scales = "free")+
  theme_minimal()+
  theme(legend.position = "bottom")
p
解决方案

核心问题是stat(density)不适合用于对数变换轴下的百分比计算——密度是连续分布的估计值,和实际计数的占比逻辑不符,且未按分面做归一化。正确做法是基于计数直接计算分面内的百分比:

修改后的代码如下:

library(ggplot2)
library(scales)

values <- sample(c(4,8,16,32,64,128,256,512),1000,replace=TRUE)
groups <- sample(c("A","B","C","D"),1000,replace=TRUE)
daf <- data.frame(group=groups,value=values)
daf$state <- "S"
daf$state[daf$group == "A" & daf$value > 16] <- "R"
daf$state[daf$group == "B" & daf$value > 64] <- "R"
daf$state[daf$group == "C" & daf$value > 32] <- "R"
daf$state[daf$group == "D" & daf$value > 256] <- "R"

p <- ggplot(daf, aes(x=value, fill=state)) +
  # 按分面计算百分比:当前区间计数 / 分面总计数 * 100
  geom_histogram(aes(y = after_stat(count) / sum(after_stat(count)) * 100), 
                 binwidth=0.5, position="stack") +
  scale_x_continuous(name = "log2-转换值", trans="log2", 
                     labels = math_format(2^.x, format = log2),
                     breaks = c(0.015625,0.03125,0.0625,0.125,0.25,0.5,0,1,2,4,8,16,32,64,128,256,512)) +
  scale_y_continuous(name = "百分比(%)", labels = percent_format(scale = 1)) +
  facet_wrap(~ group, nrow=5, ncol=3, scales = "free") +
  theme_minimal() +
  theme(legend.position = "bottom")
p
关键说明
  • after_stat(count)是ggplot2 3.3.0及以上版本的推荐用法,用于获取直方图计算后的区间计数
  • sum(after_stat(count))会自动按分面(group)计算总计数,保证百分比是相对于当前分面的整体数据
  • 若需要每个区间内的state占比为100%(即每个柱子高度统一为100%),可将position="fill",同时y轴表达式改为after_stat(count)/sum(after_stat(count)),配合labels = percent_format()即可

内容的提问来源于stack exchange,提问作者Peter Pisher

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 13:46:08