如何用ggplot geom_tile将两个相关性统计量合并为一个三角热图
合并双数据热图:分区域展示不同指标
问题描述
我用以下R代码生成了两个相关性统计热图,分别以d1和r1作为填充值,但每个热图都有一半区块信息重复。由于两个热图坐标轴完全一致,希望将它们合并为一个热图:
- 上三角(或下三角)区块展示
d1值,采用绿色系渐变配色 - 另一三角区块展示
r1值,采用红色系渐变配色 - 对角线区块使用第三种固定颜色
原始代码:
dt <- data.frame( h = rep(LETTERS[1:5], 5), j = c(rep("A", 5), rep("B", 5), rep("C", 5), rep("D", 5), rep("E", 5)), d1 = c(1, 0.717, 0.089, 0.027, 1, 0.717, 1, 0.11, 0.03, 1, 0.089, 0.11, 1, 0.464, 0.835, 0.027, 0.03, 0.464, 1, 1, 1, 1, 0.835, 1, 1), r1 = c(1, 0.462, 0.002, 0.001, 0.001, 0.462, 1, 0.003, 0.001, 0.001, 0.002, 0.003, 1, 0.054, 0.004, 0.001, 0.001, 0.054, 1, 0.001, 0.001, 0.001, 0.004, 0.001, 1) ) # 以d1为填充值的热图 ggplot(dt, aes(x = h, y = j, fill = d1)) + geom_tile(color = "black") + scale_fill_gradient(low = "white", high = "green") + geom_text(aes(label = d1), color = "black", size = 4) + coord_fixed() + theme_minimal() + labs(x = "", y = "", fill = "D") # 以r1为填充值的热图 ggplot(dt, aes(x = h, y = j, fill = r1)) + geom_tile(color = "black") + scale_fill_gradient(low = "white", high = "red") + geom_text(aes(label = r1), color = "black", size = 4) + coord_fixed() + theme_minimal() + labs(x = "", y = "", fill = "r")
解决方案
方案1:无需额外包,单比例尺适配
通过分区域绘制tile,用统一的渐变比例尺覆盖绿色和红色区间,适合快速实现:
library(ggplot2) library(dplyr) # 预处理数据:转换因子并添加索引判断区域 dt$h <- factor(dt$h, levels = LETTERS[1:5]) dt$j <- factor(dt$j, levels = LETTERS[1:5]) dt$h_idx <- as.integer(dt$h) dt$j_idx <- as.integer(dt$j) # 绘制合并热图 ggplot(dt) + # 上三角展示d1(绿色渐变) geom_tile(data = filter(dt, h_idx > j_idx), aes(x = h, y = j, fill = d1), color = "black") + # 下三角展示r1(红色渐变) geom_tile(data = filter(dt, h_idx < j_idx), aes(x = h, y = j, fill = r1), color = "black") + # 对角线固定灰色 geom_tile(data = filter(dt, h_idx == j_idx), aes(x = h, y = j), fill = "gray50", color = "black") + # 自定义渐变:白-绿-红,覆盖0-1数值范围 scale_fill_gradientn(colors = c("white", "forestgreen", "firebrick"), values = c(0, 0.5, 1), limits = c(0, 1), name = "数值") + # 添加对应区域的数值标签 geom_text(data = filter(dt, h_idx > j_idx), aes(x = h, y = j, label = round(d1, 3)), size = 4, color = "black") + geom_text(data = filter(dt, h_idx < j_idx), aes(x = h, y = j, label = round(r1, 3)), size = 4, color = "black") + geom_text(data = filter(dt, h_idx == j_idx), aes(x = h, y = j, label = "1"), size = 4, color = "white") + coord_fixed() + theme_minimal() + labs(x = "", y = "")
方案2:使用ggnewscale实现双独立图例
如果需要分别展示d1和r1的渐变图例,推荐使用ggnewscale包添加第二个填充比例尺,更清晰专业:
library(ggplot2) library(dplyr) library(ggnewscale) # 预处理数据 dt$h <- factor(dt$h, levels = LETTERS[1:5]) dt$j <- factor(dt$j, levels = LETTERS[1:5]) dt$h_idx <- as.integer(dt$h) dt$j_idx <- as.integer(dt$j) # 绘制合并热图 ggplot(dt) + # 上三角:d1绿色渐变,对应第一个图例 geom_tile(data = filter(dt, h_idx > j_idx), aes(x = h, y = j, fill = d1), color = "black") + scale_fill_gradient(low = "white", high = "forestgreen", name = "D值") + # 新建填充比例尺,用于下三角的r1 new_scale_fill() + # 下三角:r1红色渐变,对应第二个图例 geom_tile(data = filter(dt, h_idx < j_idx), aes(x = h, y = j, fill = r1), color = "black") + scale_fill_gradient(low = "white", high = "firebrick", name = "R值") + # 对角线固定灰色 geom_tile(data = filter(dt, h_idx == j_idx), aes(x = h, y = j), fill = "gray50", color = "black") + # 添加数值标签 geom_text(data = filter(dt, h_idx > j_idx), aes(x = h, y = j, label = round(d1, 3)), size = 4, color = "black") + geom_text(data = filter(dt, h_idx < j_idx), aes(x = h, y = j, label = round(r1, 3)), size = 4, color = "black") + geom_text(data = filter(dt, h_idx == j_idx), aes(x = h, y = j, label = "1"), size = 4, color = "white") + coord_fixed() + theme_minimal() + labs(x = "", y = "")
关键说明
- 通过
h_idx和j_idx判断每个区块的位置(上三角、下三角、对角线),实现分区域数据展示 - 方案1适合快速可视化,方案2的双图例更便于区分两个指标的数值梯度
- 可根据需求调整配色、标签精度和对角线样式
内容的提问来源于stack exchange,提问作者celilati
相关产品推荐
相关产品推荐

