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

如何在R的ggplot中为每个类别设置渐变颜色生成热力表?

解决ggplot热力图因数值范围差异导致小数值颜色无区分的问题

我明白你的问题——当不同类别的数值跨度极大时(比如你的A列数值集中在80-100,D列集中在0-10),全局统一的颜色渐变会让小数值列的细节完全被掩盖,根本看不出数值差异。下面我给你几个实用的解决方案,帮你给每个类别设置独立的颜色渐变,突出每列内部的数值重要性:

第一步:修正并整理你的数据

首先先把你的数据代码补全语法错误,转为数据框并整理成长格式(ggplot做热力图需要长数据格式):

set.seed(123) # 设置随机种子,保证结果可复现
library(dplyr)
library(tidyr)
library(ggplot2)

# 修正数据生成代码
dt <- as.data.frame(
  cbind(
    rbinom(10, 100, 0.9),
    rbinom(10, 100, 0.5),
    rbinom(10, 100, 0.2),
    rbinom(10, 100, 0.05)
  )
)
colnames(dt) <- c("A", "B", "C", "D")
dt$row <- paste0("Row_", 1:10) # 添加行标识,方便热力图展示

# 转为长格式
dt_long <- dt %>%
  pivot_longer(-row, names_to = "column", values_to = "value")

方案1:归一化数值(快速简单,突出相对差异)

如果你的重点是看每个类别内部的相对大小,而非绝对数值,可以对每列进行0-1归一化,把所有数值映射到同一区间,再用统一颜色渐变:

# 对每个类别单独归一化
dt_long_norm <- dt_long %>%
  group_by(column) %>%
  mutate(norm_value = scales::rescale(value, to = c(0, 1))) %>%
  ungroup()

# 绘制热力图
ggplot(dt_long_norm, aes(x = column, y = row, fill = norm_value)) +
  geom_tile(color = "white") + # 白色边框区分单元格
  geom_text(aes(label = value), size = 3) + # 显示原始数值
  scale_fill_gradient(low = "#f7fbff", high = "#08306b", name = "归一化值") +
  labs(title = "按类别归一化后的热力图", x = "类别", y = "行") +
  theme_minimal()

优点:实现简单,能快速对比每个类别内部的数值相对差异;缺点:丢失了原始数值的绝对大小信息,无法直接对比不同类别间的绝对数值。


方案2:分面独立颜色标尺(保留绝对数值,可读性强)

如果需要保留原始数值的同时看清每个类别内部的差异,推荐用patchwork包把每个类别的热力图单独绘制后拼接,每个图用独立的颜色渐变:

library(patchwork)

# 为每个类别单独绘制热力图,自定义颜色渐变
plot_A <- ggplot(filter(dt_long, column == "A"), aes(x = column, y = row, fill = value)) +
  geom_tile(color = "white") +
  geom_text(aes(label = value), size = 3) +
  scale_fill_gradient(low = "#fff7bc", high = "#cc4c02", name = "A类数值") +
  labs(x = NULL, y = "行") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))

plot_B <- ggplot(filter(dt_long, column == "B"), aes(x = column, y = row, fill = value)) +
  geom_tile(color = "white") +
  geom_text(aes(label = value), size = 3) +
  scale_fill_gradient(low = "#f1eef6", high = "#990000", name = "B类数值") +
  labs(x = NULL, y = NULL) +
  theme_minimal() +
  theme(axis.text.y = element_blank())

plot_C <- ggplot(filter(dt_long, column == "C"), aes(x = column, y = row, fill = value)) +
  geom_tile(color = "white") +
  geom_text(aes(label = value), size = 3) +
  scale_fill_gradient(low = "#e5f5f9", high = "#2ca25f", name = "C类数值") +
  labs(x = NULL, y = NULL) +
  theme_minimal() +
  theme(axis.text.y = element_blank())

plot_D <- ggplot(filter(dt_long, column == "D"), aes(x = column, y = row, fill = value)) +
  geom_tile(color = "white") +
  geom_text(aes(label = value), size = 3) +
  scale_fill_gradient(low = "#fef0d9", high = "#d7301f", name = "D类数值") +
  labs(x = NULL, y = NULL) +
  theme_minimal() +
  theme(axis.text.y = element_blank())

# 拼接所有图
plot_A + plot_B + plot_C + plot_D +
  plot_layout(nrow = 1) +
  plot_annotation(title = "每个类别独立颜色标尺的热力图")

优点:每个类别用独立的颜色渐变,能清晰看到内部数值差异,同时保留原始数值;还可以给每个类别设置不同的颜色主题,强化类别区分;缺点:需要多写几行代码,但逻辑很清晰。


方案3:同一图内多颜色标尺(适合同一视图对比)

如果你想把所有类别放在同一个热力图里,同时用不同的颜色渐变,可以用ggnewscale包实现多组颜色标尺:

library(ggnewscale)

ggplot() +
  # 绘制A类
  geom_tile(data = filter(dt_long, column == "A"), 
            aes(x = column, y = row, fill = value), color = "white") +
  geom_text(data = filter(dt_long, column == "A"), 
            aes(x = column, y = row, label = value), size = 3) +
  scale_fill_gradient(low = "#fff7bc", high = "#cc4c02", name = "A类数值") +
  
  # 新建颜色标尺
  new_scale_fill() +
  
  # 绘制B类
  geom_tile(data = filter(dt_long, column == "B"), 
            aes(x = column, y = row, fill = value), color = "white") +
  geom_text(data = filter(dt_long, column == "B"), 
            aes(x = column, y = row, label = value), size = 3) +
  scale_fill_gradient(low = "#f1eef6", high = "#990000", name = "B类数值") +
  
  new_scale_fill() +
  
  # 绘制C类
  geom_tile(data = filter(dt_long, column == "C"), 
            aes(x = column, y = row, fill = value), color = "white") +
  geom_text(data = filter(dt_long, column == "C"), 
            aes(x = column, y = row, label = value), size = 3) +
  scale_fill_gradient(low = "#e5f5f9", high = "#2ca25f", name = "C类数值") +
  
  new_scale_fill() +
  
  # 绘制D类
  geom_tile(data = filter(dt_long, column == "D"), 
            aes(x = column, y = row, fill = value), color = "white") +
  geom_text(data = filter(dt_long, column == "D"), 
            aes(x = column, y = row, label = value), size = 3) +
  scale_fill_gradient(low = "#fef0d9", high = "#d7301f", name = "D类数值") +
  
  labs(title = "同一图内多颜色标尺的热力图", x = "类别", y = "行") +
  theme_minimal()

优点:所有类别在同一视图,方便横向对比;缺点:图例较多,可能会占用较多空间,需要注意排版。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:21:35