ggplot2中geom_hex()为何未使用完整颜色刻度?
问题:geom_hex() 颜色映射不符合预期
环境
- R 版本:3.6.0
- {ggplot2} 版本:3.4.0
复现代码
library(ggplot2) library(cowplot) library(hexbin) df <- data.frame(x = rnorm(1000), y = rnorm(1000)) plot_grid( ggplot(df) + geom_bin_2d(aes(x = x, y = y)), ggplot(df) + geom_hex(aes(x = x, y = y)), labels = c("bin", "hex"), label_size = 12 )
问题现象
两个图表的图例数值范围一致(0至约12.5),颜色映射为深蓝到浅蓝:
geom_bin_2d()图表中间为浅蓝、外围为深蓝,符合正态分布的预期;geom_hex()图表几乎全为深蓝,无明显浅蓝区域,仅存在少量颜色变化。
手动用hexbin()验证计数范围正常:
> summary(hexbin(df$x, df$y)) 'hexbin' object from call: hexbin(x = df$x, y = df$y) n = 1000 points in nc = 351 hexagon cells in grid dimensions 36 by 31 cell count xcm ycm Min. : 18.0 Min. : 1.000 Min. :-3.54600 Min. :-3.06479 1st Qu.: 389.5 1st Qu.: 1.000 1st Qu.:-0.91158 1st Qu.:-0.92188 Median : 565.0 Median : 2.000 Median : 0.02048 Median : 0.07285 Mean : 559.9 Mean : 2.849 Mean : 0.04781 Mean : 0.03474 3rd Qu.: 726.5 3rd Qu.: 4.000 3rd Qu.: 0.98753 3rd Qu.: 0.98776 Max. :1098.0 Max. :12.000 Max. : 4.50242 Max. : 3.02475
请问为何geom_hex()没有正确将计数映射至fill美学?
解决方案
问题根源
geom_bin_2d() 和 geom_hex() 在ggplot2 3.4.0中默认使用的颜色比例尺不一致:
geom_bin_2d()自动使用 viridis 连续色阶(scale_fill_viridis_c()),该色阶的高值(高计数)对应明亮的浅色调,视觉对比度高,高计数区域更显眼;geom_hex()默认仍使用传统的连续渐变色阶(scale_fill_continuous()),颜色对比度较低,且由于六边形分箱的特性,高计数的六边形数量少、面积小,导致浅色调区域不明显,整体看起来偏深蓝。
同时两者分箱逻辑存在差异:geom_bin_2d() 默认30×30的矩形分箱,高计数单元更密集,视觉上浅蓝区域更大;而geom_hex() 的六边形分箱单元数量更少(示例中为351个),高计数单元更集中,视觉占比小。
修复方法
方法1:统一颜色比例尺
给geom_hex()添加和geom_bin_2d()一致的viridis色阶,提升高值区域辨识度:
plot_grid( ggplot(df) + geom_bin_2d(aes(x = x, y = y)), ggplot(df) + geom_hex(aes(x = x, y = y)) + scale_fill_viridis_c(), labels = c("bin", "hex"), label_size = 12 )
方法2:调整分箱数量
增加geom_hex()的bins参数,让分箱更细密,高计数区域更分散:
plot_grid( ggplot(df) + geom_bin_2d(aes(x = x, y = y)), ggplot(df) + geom_hex(aes(x = x, y = y), bins = 50) + scale_fill_viridis_c(), labels = c("bin", "hex"), label_size = 12 )
方法3:自定义颜色渐变
如果偏好传统配色,可手动调整颜色对比度:
plot_grid( ggplot(df) + geom_bin_2d(aes(x = x, y = y)), ggplot(df) + geom_hex(aes(x = x, y = y)) + scale_fill_gradient(low = "#001f3f", high = "#7fdbff"), labels = c("bin", "hex"), label_size = 12 )
验证
修改后,geom_hex()的颜色映射会和geom_bin_2d()一致,中间高计数区域显示浅蓝,外围低计数区域显示深蓝,符合正态分布预期。
内容的提问来源于stack exchange,提问作者Michael Henry
相关产品推荐
相关产品推荐

