如何调整ggplot热图色阶展示更多颜色,区分跨度极大的z值
你的问题根源是z值跨了超过10个数量级,默认线性色阶会把99%的颜色区分度分配给极值和最大值之间的区间,导致占绝大多数的1e-5~1e-2区间被压缩成同色。可以通过以下几种方案解决:
方案1:对数变换色阶(最适合多数量级跨度数据)
直接将填充色的映射刻度改为对数刻度,让不同数量级的z值都能获得均等的色阶区分度:
library(tidyverse) x <- seq(3, 5, by = 1) y <- seq(5, 101, by = 2) z <- seq(3, 10^-13, length = 146) # 修正原代码语法错误,无需转换为矩阵 combinations <- expand_grid(x, y) %>% filter(y > x) %>% mutate(z = z) combinations %>% ggplot(aes(x = x, y = y)) + geom_tile(aes(fill = z)) + # 对数色阶,可自定义颜色序列、标签格式 scale_fill_viridis_c( trans = "log10", name = "z值(对数刻度)", breaks = 10^seq(-13, -1, 2), labels = scales::label_scientific() )
该方案下1e-13的极小值会和其他数量级的数值有明显颜色区分,1e-5~1e-2区间也能呈现细腻的颜色渐变。
方案2:自定义分段色阶(重点突出关注区间的精细度)
如果不想用对数刻度,可以手动设置色阶断点,给你关注的1e-5~1e-2区间分配更多的颜色节点,极小值单独分配颜色:
combinations %>% ggplot(aes(x = x, y = y)) + geom_tile(aes(fill = z)) + scale_fill_gradientn( colours = c("darkblue", "blue", "cyan", "green", "yellow", "orange", "red"), # 手动设置断点,1e-5到1e-2区间插入更多断点提升精细度 values = scales::rescale(c(1e-13, 1e-7, 1e-5, 5e-5, 1e-4, 5e-4, 1e-3, 5e-3, 1e-2)), limits = c(1e-13, 1e-2), na.value = "grey50", name = "z值" )
调整values里的断点密度就能控制对应区间的色阶精细度,断点越密的区间颜色区分度越高。
方案3:截断极端值(不需要保留极值精确信息时最优)
如果1e-13这个极小值只需要标识存在、不需要展示精确大小,可以将低于阈值的数值统一截断,把全部色阶空间留给你关注的核心区间:
combinations %>% mutate(z_trunc = ifelse(z < 1e-5, 1e-5, z)) %>% # 低于1e-5的统一设为1e-5 ggplot(aes(x = x, y = y)) + geom_tile(aes(fill = z_trunc)) + scale_fill_viridis_c( name = "z值", limits = c(1e-5, 1e-2), labels = ~ifelse(.x == 1e-5, "<=1e-5", scales::label_scientific()(.x)), oob = scales::oob_squish # 超出限值的数值统一映射为限值对应的颜色 )
该方案下1e-5~1e-2区间的色阶精细度最高,极小值会用色阶最左侧的颜色单独标识,非常容易识别。
内容的提问来源于stack exchange,提问作者AW27
相关产品推荐
相关产品推荐

