如何在ggplot中设置带固定中点的渐变颜色刻度?
解决方案:固定颜色刻度中点为0的条形图
当z_score仅包含负值时,要让颜色刻度中点固定在0(0对应白色,负值向蓝色过渡),可以通过手动控制颜色映射的范围和对应关系实现,以下是两种可行方法:
方法1:使用scale_fill_gradientn手动指定映射规则
核心是通过limits固定颜色刻度的范围(必须包含0),并通过values参数将颜色对应到相对的z_score位置:
# 构造仅含负值的测试数据 data_2 <- data.frame( name = paste('Pathway', 1:5), p_val = c(0.01, 0.05, 0.03, 0.001, 0.02), z_score = c(-2, -3, -1.5, -4, -2.5) ) # 计算对称的刻度范围(确保包含0) z_range <- max(abs(data_2$z_score)) data_2 |> ggplot(aes(x = p_val, y = fct_reorder(name, p_val))) + geom_bar(aes(fill = z_score), stat = 'identity') + scale_fill_gradientn( colours = c('#709AE1', '#FFFFFF', '#FD7446'), # 蓝-白-红的渐变 limits = c(-z_range, z_range), # 固定刻度范围为对称区间,包含0 values = scales::rescale(c(-z_range, 0, z_range)), # 将颜色对应到刻度的相对位置 breaks = seq(-z_range, z_range, by = 1), # 可选:设置刻度断点 labels = seq(-z_range, z_range, by = 1) # 可选:设置刻度标签 )
参数说明:
limits:强制颜色刻度覆盖从-z_range到z_range的区间,确保0始终在刻度中点values:通过scales::rescale将实际的z_score值转换为0-1之间的相对位置,让白色严格对应0,蓝色对应最小负值,红色对应最大正值(即使数据中没有正值,刻度仍会保留该区间)
方法2:使用scale_fill_gradient2(更简洁的对称渐变)
scale_fill_gradient2专门用于中点固定的双色/三色渐变,直接指定中点、低色和高色即可:
data_2 |> ggplot(aes(x = p_val, y = fct_reorder(name, p_val))) + geom_bar(aes(fill = z_score), stat = 'identity') + scale_fill_gradient2( low = '#709AE1', # 负值对应的颜色 mid = '#FFFFFF', # 中点(0)对应的颜色 high = '#FD7446', # 正值对应的颜色 midpoint = 0, # 固定中点为0 limits = c(-z_range, z_range) # 可选:固定刻度范围,避免数据全负时自动收缩 )
这种方法更直观,适合需要对称颜色刻度且中点固定为0的场景,当数据包含正负值时也能自动适配,无需修改代码。
内容的提问来源于stack exchange,提问作者CheesyGnocchi
相关产品推荐
相关产品推荐

