使用ggplot绘制堆叠百分比直方图的数值求和问题求助
问题描述
给定如下数据:
class subclass percent A X 7.75 A Y 7.75 B Z 1.25 B Z 1.25 B T 1.25
需求是绘制一幅堆叠柱形图:
- x轴为
class类别(仅A、B两个柱子) - y轴为
percent的最终数值(A柱对应7.75,B柱对应1.25) - 柱子按
subclass填充颜色,其中A柱X、Y各占50%,B柱Z占约66%、T占约33%
尝试使用ggplot的geom_histogram编写代码如下:
data %>% ggplot(aes(x=reorder(class,-percent), y = percent, fill = subclass)) + geom_histogram(stat='identity') + scale_y_continuous(labels = scales::percent)
但代码会将同一class下的percent数值求和,导致A柱显示15.5、B柱显示3.75,不符合预期,不清楚fill=subclass是否生效,求错误原因及解决方法。
错误原因及解决方法
核心错误点
- 几何对象选择错误:
geom_histogram的设计初衷是对数据做分箱统计,即便设置stat='identity',它仍会默认对同一x分组下的y值做求和堆叠,这就是A、B柱数值翻倍/三倍的原因。你需要的是展示已知数值的堆叠柱形图,应该用geom_col(默认stat='identity',专门用于自定义数值的柱形图)。 - 数据未做预处理:原始数据中,同一
class下的percent是最终目标值,而非每个subclass的占比拆分值,直接绘图会导致重复叠加。
正确实现步骤
- 预处理数据:先统计每个
class下各subclass的出现频次,计算占比后,再乘以对应class的目标percent值,得到每个子类的拆分数值:
library(dplyr) library(ggplot2) processed_data <- data %>% # 统计每个class-subclass组合的数量 group_by(class, subclass) %>% tally() %>% # 基于class分组,计算子类占比和目标百分比 group_by(class) %>% mutate( total_count = sum(n), subclass_ratio = n / total_count, # 提取该class对应的目标percent(同一class的percent值一致,取第一个即可) target_percent = unique(data$percent[data$class == first(class)]) ) %>% # 计算每个子类对应的y轴数值 mutate(y_value = subclass_ratio * target_percent)
- 绘制堆叠柱形图:用
geom_col实现堆叠效果,fill=subclass会正常生效:
processed_data %>% ggplot(aes(x = reorder(class, -target_percent), y = y_value, fill = subclass)) + geom_col() + # 将y轴格式化为百分比显示 scale_y_continuous(labels = function(x) paste0(round(x, 2), "%")) + labs(x = "类别(Class)", y = "百分比(Percent)", fill = "子类别(Subclass)")
效果说明
预处理后的数据中,A类的X、Y各对应3.88(7.7550%),B类的Z对应0.83(1.2566.67%)、T对应0.42(1.25*33.33%),堆叠后正好是目标的7.75和1.25,不同子类会以不同颜色填充对应柱子的拆分区域。
内容的提问来源于stack exchange,提问作者cookiemonster
相关产品推荐
相关产品推荐

