ggplot2 facet_wrap分组柱状图如何按分面显示占比而非计数
需求说明
使用的数据框包含两个因子变量:
cls:共3个水平subset:共2个水平
需要对比subset两个分组下不同cls类别的分布,要求y轴展示占比(百分比)替代原始计数,且占比需在单个subset分面组内独立计算,不能基于全数据集统计。
示例数据构造代码:
library(tidyverse) data = data.frame( x = rnorm(1000), cls = factor(c(rep("A", 200), rep("B", 300), rep("C", 500))), subset = factor(c(rep("train", 900), rep("test", 100))) )
问题复现
初始错误实现
初始代码直接在geom_bar中计算全局占比,未按分面分组单独统计,不符合需求:
ggplot(data, aes(x = cls, fill = cls)) + geom_bar(aes(y = ..count.. / sum(..count..))) + facet_wrap(~subset)
错误效果:
可以看到test组所有类别占比加和仅为10%,是因为计算时用了全数据集1000条作为分母,没有按test组自身100条样本计算占比。
自定义函数报错问题
参考思路编写通用绘图函数时运行报错,原函数代码:
plot_train_vs_test = function(data, var, subset_colname){ plot_data = data %>% count(var, eval(subset_colname)) %>% group_by(eval(subset_colname)) %>% mutate(perc = n/sum(n)) ggplot(plot_data, aes(x = var, y = perc, fill = var)) + geom_col() + scale_y_continuous(labels = scales::label_percent()) + facet_wrap(~eval(subset_colname)) } plot_train_vs_test(data, "cls", "subset")
报错核心原因是dplyr和ggplot2的非标准评估逻辑下,直接传入字符串列名、用eval()简单包裹无法正确识别列。
正确实现方案
方案1:直接在绘图层计算分面内占比
不需要提前汇总数据,利用ggplot内置的分面标识变量PANEL,为每个分面单独计算分母总和:
ggplot(data, aes(x = cls, fill = cls)) + geom_bar(aes(y = after_stat(count / tapply(count, PANEL, sum)[PANEL]))) + scale_y_continuous(labels = scales::label_percent()) + facet_wrap(~subset) + labs(y = "组内占比")
实现逻辑:PANEL是ggplot生成分面时自动创建的分组变量,tapply(count, PANEL, sum)会返回每个分面的总样本数,匹配到对应分面的柱子作为分母,即可得到每个分面内的独立占比。
方案2:提前汇总数据(适配自定义函数场景)
使用tidyverse的.data代词引用字符串形式的列名,修复非标准评估导致的报错,修复后的通用函数:
plot_train_vs_test = function(data, var, subset_colname){ plot_data = data %>% # 用.data[[字符串]] 正确引用列名 count(.data[[var]], .data[[subset_colname]]) %>% group_by(.data[[subset_colname]]) %>% mutate(perc = n/sum(n)) ggplot(plot_data, aes(x = .data[[var]], y = perc, fill = .data[[var]])) + geom_col() + scale_y_continuous(labels = scales::label_percent()) + facet_wrap(~.data[[subset_colname]]) + labs(x = var, y = "组内占比", fill = var) } # 测试运行 plot_train_vs_test(data, "cls", "subset")
运行后两个分面内的类别占比各自加和为100%,符合需求。
内容的提问来源于stack exchange,提问作者stats_b
相关产品推荐
相关产品推荐

