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

R ggplot绘制分面柱状图:按分组算占比、第三变量填色异常求助

问题原因

  1. 全局映射中group = group的优先级高于fill = sex,导致ggplot统计计数时没有按sex维度拆分,因此填充色无法生效;同时你在scale_fill_manual中传入了3个颜色值,但sex只有Female、Male两个类别,颜色匹配也存在异常。
  2. 直接在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 22:24:03