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

如何对ggplot的geom_bin2d()按x轴分组进行归一化处理?

实现按age分组的value相对分布热力图

要实现每个age区间内value的相对分布热力图,核心是对每个age分组内的value区间计数做归一化(计算占该age分组总样本的比例),消除不同age区间样本量差异带来的偏差。以下是两种可行方案:

方法一:手动预处理数据后绘制热力图

先对数据进行分箱、计数并计算相对比例,再用geom_tile绘制热力图,这种方式更灵活,便于自定义分箱规则:

# 加载所需包
library(ggplot2)
library(dplyr)
library(stringr)

# 生成示例数据
set.seed(1e3)
n <- 1e3
dt <- data.frame(
  age = 50*rbeta(n, 5, 1),
  value =  1000*rbeta(n, 1, 3)
)

# 按默认30个分箱对age和value分组,计算每个箱的计数
dt_binned <- dt %>%
  mutate(
    age_bin = cut(age, breaks = 30, labels = FALSE),
    value_bin = cut(value, breaks = 30, labels = FALSE)
  ) %>%
  count(age_bin, value_bin) %>%
  # 按age分组计算每个value区间的相对比例
  group_by(age_bin) %>%
  mutate(prop = n / sum(n)) %>%
  ungroup()

# 提取分箱的区间起始值用于坐标轴标签
age_intervals <- cut(dt$age, breaks = 30)
value_intervals <- cut(dt$value, breaks = 30)

dt_binned <- dt_binned %>%
  left_join(
    data.frame(
      age_bin = seq_along(levels(age_intervals)),
      age_center = levels(age_intervals) %>% str_extract("(?<=\\()[0-9.]+(?=,)") %>% as.numeric()
    ),
    by = "age_bin"
  ) %>%
  left_join(
    data.frame(
      value_bin = seq_along(levels(value_intervals)),
      value_center = levels(value_intervals) %>% str_extract("(?<=\\()[0-9.]+(?=,)") %>% as.numeric()
    ),
    by = "value_bin"
  )

# 绘制热力图
ggplot(dt_binned, aes(x = age_center, y = value_center, fill = prop)) +
  geom_tile(color = "white", size = 0.1) + # 添加白色边框区分箱
  scale_fill_viridis_c(name = "相对比例") +
  labs(x = "age", y = "value") +
  theme_minimal()

方法二:用stat_summary_2d直接在ggplot中计算比例

利用stat_summary_2d可以直接对每个x-y分箱应用自定义函数,无需手动预处理数据,代码更简洁:

library(ggplot2)

# 生成示例数据
set.seed(1e3)
n <- 1e3
dt <- data.frame(
  age = 50*rbeta(n, 5, 1),
  value =  1000*rbeta(n, 1, 3)
)

# 绘制相对分布热力图
ggplot(dt, aes(x = age, y = value)) +
  stat_summary_2d(
    fun = function(y) {
      # 对当前age分组内的value进行分箱
      y_bins <- cut(y, breaks = 30, labels = FALSE)
      # 计算每个value分箱的相对比例
      bin_counts <- table(y_bins)
      bin_props <- bin_counts / sum(bin_counts)
      # 返回每个数据点对应的比例值
      bin_props[as.character(y_bins)] %>% as.numeric()
    },
    bins = 30
  ) +
  scale_fill_viridis_c(name = "相对比例") +
  labs(x = "age", y = "value") +
  theme_minimal()

说明

两种方法最终都会生成每个age区间内value的相对分布热力图,每个age列的颜色代表该value区间占该age组总样本的比例,完全消除了不同age区间样本量的差异,能清晰对比各age组内value的分布模式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 12:36:18