R ggplot绘制分面柱状图:按分组算占比、第三变量填色异常求助
问题原因
- 全局映射中
group = group的优先级高于fill = sex,导致ggplot统计计数时没有按sex维度拆分,因此填充色无法生效;同时你在scale_fill_manual中传入了3个颜色值,但sex只有Female、Male两个类别,颜色匹配也存在异常。 - 直接在
geom_bar中用..prop..计算占比的分组逻辑灵活度低,很容易和fill、facet的分组逻辑冲突。
解决方案
提前用dplyr汇总计算你需要的占比,完全可控分组逻辑,不需要在ggplot内部做统计计算,修改后代码如下:
library(tidyverse) # 模拟数据(和原有逻辑一致) lengths <- sample(x = c(12, 15, 20, 25, 30, 32, 35, 40, 45, 60), size = 1000, replace = TRUE) group <- sample(c("A", "B", "C", "D"), size = 1000, replace = TRUE) sex <- sample(c("Female", "Male"), size = 1000, replace = TRUE) data <- data.frame(lengths = lengths, sex = sex, group = group) rm(lengths, group, sex) # 补充Total分组 + 提前计算占比(按每个group的总样本数计算,完全符合需求) plot_data <- data %>% bind_rows(mutate(data, group = "Total")) %>% # 按group、lengths、sex分组计数 count(group, lengths, sex, name = "cnt") %>% # 按group分组计算占比 group_by(group) %>% mutate(prop = cnt / sum(cnt)) %>% ungroup() # 绘图 ggplot(plot_data, aes(x = lengths, y = prop, fill = sex)) + geom_col(color = "black", position = "stack") + # 堆叠柱状图和原有逻辑一致 labs(y = "%", fill = "sex") + facet_wrap(~ group, nrow = 6, strip.position = "right", scales = "free") + scale_x_continuous(limits = c(20,80)) + scale_y_continuous(labels = scales::percent) + theme( legend.position = c(.75, .95), legend.background = element_rect(fill = "white", color = "black"), axis.line = element_line(color = "black"), panel.background = element_blank(), legend.direction = "horizontal", strip.background = element_blank(), strip.text.y = element_blank() ) + # 仅传入2个颜色和sex的两个类别匹配 scale_fill_manual(values = c("purple", "blue"))
这里用geom_col替代原来的geom_bar(stat = "count"),直接使用提前计算好的prop作为y值,既保证了占比是按每个group的总数量计算,也不会干扰fill的映射逻辑,柱子会正常按sex区分填充色。
内容的提问来源于stack exchange,提问作者Daniel Estévez
相关产品推荐
相关产品推荐

