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

ggplot2双变量绘图如何保留unit字段并展示百分比值

问题原因

之前使用的aes(y = (..count..)/sum(..count..))写法无法得到目标结果,核心原因有两个:

  • geom_col()默认调用stat_identity()统计变换,直接读取传入的y变量原始值,不会生成..count..这个计数统计量,这套语法仅适用于默认做行数统计的geom_bar()
  • 即便语法适配,..count..统计的是每个品牌对应的观测行数,完全没有调用unit字段的销量值,输出的是样本数占比,和需要的销量占比需求不匹配。
解决方案

最稳妥、逻辑最可控的写法是在数据预处理阶段先算好对应分组的销量占比,再传入ggplot绘图,尤其是后续要跨SES组对比的话,这种写法不会出现统计范围错位的问题。

单SES组绘图代码

df1 %>% 
  filter(SES == "1") %>%
  # 按品牌汇总总销量
  group_by(brand) %>%
  summarise(brand_unit = sum(unit)) %>%
  # 计算当前SES组内各品牌销量占比,乘100转百分比数值
  mutate(unit_perc = brand_unit / sum(brand_unit) * 100) %>%
  ggplot(aes(x = brand, y = unit_perc)) +
  geom_col() +
  # y轴直接显示百分比后缀
  scale_y_continuous(labels = ~paste0(.x, "%")) +
  labs(
    y = "Share of total units sold",
    x = "Brand",
    title = "Buying Behaviour SES 1"
  ) +
  theme_bw(base_size = 15)

多SES组对比扩展

如果要直接对比所有SES分组的品牌占比,不需要逐组过滤绘图,只要调整分组逻辑加分面即可,每个分面会自动计算组内百分比,跨组视觉对比完全不受各组总销量绝对值差异影响:

df1 %>% 
  # 按SES、品牌两个维度分组汇总销量
  group_by(SES, brand) %>%
  summarise(brand_unit = sum(unit), .groups = "drop_last") %>%
  # 按SES分组计算组内各品牌销量占比
  mutate(unit_perc = brand_unit / sum(brand_unit) * 100) %>%
  ggplot(aes(x = brand, y = unit_perc)) +
  geom_col() +
  scale_y_continuous(labels = ~paste0(.x, "%")) +
  # 按SES组分面
  facet_wrap(~SES, labeller = labeller(SES = ~paste("SES Group", .x))) +
  labs(
    y = "Share of total units sold",
    x = "Brand",
    title = "Buying Behaviour by SES Group"
  ) +
  theme_bw(base_size = 15)

注意:summarise后的.groups = "drop_last"参数是为了保留SES作为分组维度计算占比,如果使用的dplyr版本低于1.0.0,可以删掉这个参数,算完mutate后手动加ungroup()即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 11:18:26