You need to enable JavaScript to run this app. ggplot2聚合总收益后如何按不同类型列填充直方图?
优惠活动
大模型
产品
解决方案
定价
更多

ggplot2聚合总收益后如何按不同类型列填充直方图?

适配“个体年度总收益”统计逻辑的分色直方图实现方案

核心问题本质

宽表场景下无法直接给geom_histogram()加颜色填充,核心原因是ggplot的fill审美映射要求绑定一维离散分类变量,你当前宽表中的三个独立哑变量(typeA/typeB/typeC)是三个平行的0/1列,不满足单维度分类的映射要求,需要先基于研究目标的分类规则,给每一行“个体-年度”记录匹配对应的收入类型标签,再绑定到fill参数即可。

分类规则前置(绘图的核心前提)

分色逻辑必须先匹配研究目标,不能直接硬编码分类,两种常用的符合统计逻辑的规则如下:

  • 规则1(匹配“按收入类型分区展示总收益分布”的核心需求):定义每个“个体-年度”记录的主导收入类型作为分类维度,即取该个体当年三类收入中总金额占比最高的类型,作为该条总收益记录的填充色分类。该规则下的直方图计数逻辑为:每个收益区间的总计数是区间内所有个体-年度样本数,区间内不同颜色的分层对应该区间内不同主导收入类型的样本占比,完全避免长表单笔收入计入统计的偏差。
  • 规则2(匹配“不同收入类型对应的总收益覆盖范围”的展示需求):将当年存在对应类型收入的个体-年度记录,全部纳入对应类型的直方图统计。该规则下因为个体可能同时有多种收入类型,不同类型的直方图会存在重叠,适合用半透明效果展示分布差异。

可直接复用的代码实现

基于规则1(主导收入类型)的堆叠分色直方图

首先从原始长表data直接聚合得到带分类标签的数据集(避免只存笔数的聚合偏差,推荐直接从原始长表重新计算,不要基于已有宽表的哑变量列硬推):

library(dplyr)
library(ggplot2)
library(tidyr)

agg_df <- data %>%
  # 按个体+年度聚合
  group_by(ID, year) %>%
  summarise(
    income_sum = sum(income),
    # 同步计算每类收入的年度总金额
    typeA_amt = sum(income[type == "A"]),
    typeB_amt = sum(income[type == "B"]),
    typeC_amt = sum(income[type == "C"]),
    .groups = "drop"
  ) %>%
  rowwise() %>%
  # 计算主导收入类型
  mutate(
    dominant_type = case_when(
      which.max(c_across(c(typeA_amt, typeB_amt, typeC_amt))) == 1 ~ "A",
      which.max(c_across(c(typeA_amt, typeB_amt, typeC_amt))) == 2 ~ "B",
      TRUE ~ "C"
    )
  )

完成数据处理后,直接将分类列绑定到fill参数绘图,即可得到符合统计逻辑的分色直方图:

h <- ggplot(agg_df, aes(x = income_sum, fill = dominant_type)) +
  # 调整position为"stack"实现堆叠分色,如需并列分色可改为"dodge"
  geom_histogram(binwidth = 你设定的组距, position = "stack", alpha = 0.8) +
  labs(x = "个人年度总收益", fill = "主导收入类型")

基于规则2(有该类收入即纳入)的重叠分色直方图

如果需要展示只要有某类收入的个体总收益分布,可将聚合后的宽表转成长格式筛选后绘图:

long_plot_df <- agg_df %>%
  # 将三个类型的金额列转成长格式
  pivot_longer(
    cols = c(typeA_amt, typeB_amt, typeC_amt),
    names_to = "income_type",
    values_to = "type_amt"
  ) %>%
  # 仅保留当年有对应类型收入的记录
  filter(type_amt > 0)

# 绘图
h <- ggplot(long_plot_df, aes(x = income_sum, fill = income_type)) +
  # position设为"identity"实现重叠效果,alpha调整透明度避免色块遮挡
  geom_histogram(binwidth = 你设定的组距, position = "identity", alpha = 0.5) +
  labs(x = "个人年度总收益", fill = "收入类型")

常见避坑提醒

  • 不要直接基于宽表的三个0/1哑变量映射颜色:平行的多列哑变量无法直接作为单维度分类值传入fill参数,强行转换会导致分类逻辑错乱。
  • 不要用收入笔数判断主导类型:同样是2笔A类、1笔C类收入,很可能C类总金额远高于A类,仅靠笔数计算的主导类型存在统计偏差,优先按金额占比计算分类。
  • 存在边界情况(三类收入金额完全相等)时,可在case_when中新增判断逻辑,将这类样本归为“混合收入类型”,避免分类遗漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 14:36:04