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

ggplot2中geom_hexbin分箱计数与渐变填充颜色映射不准确问题

问题:ggplot2中geom_hex分箱计数与渐变填充映射不准确

我尝试使用ggplot2绘制分箱散点图,基础代码如下:

library(ggplot2)
bks = seq(from = 0, to = 10000, by = 1000)
d <- ggplot(diamonds, aes(carat, price)) + theme_bw()
d + geom_point(alpha = 0.01)

使用geom_hex时,分箱计数与渐变刻度的映射不准确:

d + geom_hex(aes(fill = after_stat(count)), bins = 30, colour = "white") + 
  scale_fill_distiller(palette = "Spectral", breaks = bks) +
  geom_text(data = diamonds, aes(x = carat, y = price, label = after_stat(count)),
          stat="binhex", bins=30, show.legend=FALSE,
          colour="black", size=2.5)

例如计数为5809和5556的分箱仍显示为蓝色。但使用geom_bin_2d时,映射是准确的:

d + geom_bin_2d(aes(fill = after_stat(count)), bins = 30) + 
  scale_fill_distiller(palette = "Spectral", breaks = bks) +
  geom_text(data = diamonds, aes(x = carat, y = price, label = after_stat(count)),
            stat="bin_2d", bins=30, show.legend=FALSE,
            colour="black", size=2.5)

问题原因

  1. 调色板类型不匹配:Spectral是发散型调色板,但scale_fill_distiller默认使用type="seq"(顺序型)逻辑解析调色板,导致颜色映射的区间划分错误,高数值分箱无法正确对应到调色板的深色(红色)区域。
  2. 分箱计算重复的潜在偏差:geom_hex和geom_text各自独立计算分箱,即使参数相同,也可能因计算细节出现微小差异,导致文本显示的count与六边形填充的count不完全匹配。

解决方法

方法1:正确配置发散型调色板

在scale_fill_distiller中指定type="div",并设置合适的midpoint(通常取count的中位数或均值),让发散型调色板正确映射数值范围:

# 计算分箱count的中位数作为映射中点
count_mid <- median(ggplot2:::binhex(diamonds$carat, diamonds$price, bins=30)$count)

d + geom_hex(aes(fill = after_stat(count)), bins = 30, colour = "white") + 
  scale_fill_distiller(palette = "Spectral", breaks = bks, 
                       type = "div", midpoint = count_mid) +
  geom_text(stat="binhex", bins=30, 
            aes(label = after_stat(count)),
            show.legend=FALSE, colour="black", size=2.5)

方法2:改用顺序型调色板

如果不需要发散型配色,直接使用顺序型调色板(如"Reds"、"Blues"),无需额外配置类型:

d + geom_hex(aes(fill = after_stat(count)), bins = 30, colour = "white") + 
  scale_fill_distiller(palette = "Reds", breaks = bks) +
  geom_text(stat="binhex", bins=30, 
            aes(label = after_stat(count)),
            show.legend=FALSE, colour="black", size=2.5)

方法3:预计算分箱数据(彻底避免分箱差异)

先统一计算六边形分箱的结果,再基于该数据绘制图形,确保填充和文本使用完全一致的count值:

# 预计算分箱数据
hex_data <- ggplot_build(d + geom_hex(aes(fill = after_stat(count)), bins=30))$data[[1]]

# 绘制图形
d + geom_hex(data = hex_data, aes(x = x, y = y, fill = count), 
             bins = 30, colour = "white") +
  scale_fill_distiller(palette = "Spectral", breaks = bks, 
                       type = "div", midpoint = median(hex_data$count)) +
  geom_text(data = hex_data, aes(x = x, y = y, label = count),
            show.legend=FALSE, colour="black", size=2.5)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:01:20