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

如何在ggplot2中基于阈值实现不同填充渐变效果?

瓷砖图(Tile Plot)分组渐变填充问题

数据

dat <- structure(list(Date = structure(c(19913, 19913, 19913, 19913, 
19914, 19914, 19914, 19914, 19915, 19915, 19915, 19915, 19916, 
19916, 19916, 19916), class = "Date"), meal = structure(c(1L, 
2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), levels = c("Fasting", 
"Breakfast", "Lunch", "Dinner"), class = "factor"), value = c(NA, 
NA, 121, 136, 75, 82, 86, 114, 80, 81, 78, 90, 75, 91, NA, NA
), threshold = c(NA, NA, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, 
TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, NA, NA)), row.names = c(NA, 
-16L), class = "data.frame")

数据预览:

Date       meal      value threshold
   <date>     <fct>     <dbl> <lgl>    
 1 2024-07-09 Fasting      NA NA       
 2 2024-07-09 Breakfast    NA NA       
 3 2024-07-09 Lunch       121 FALSE       
 4 2024-07-09 Dinner      136 FALSE    
 5 2024-07-10 Fasting      75 TRUE     
 6 2024-07-10 Breakfast    82 TRUE     
 7 2024-07-10 Lunch        86 TRUE     
 8 2024-07-10 Dinner      114 TRUE     
 9 2024-07-11 Fasting      80 TRUE     
10 2024-07-11 Breakfast    81 TRUE     
11 2024-07-11 Lunch        78 TRUE     
12 2024-07-11 Dinner       90 TRUE     
13 2024-07-12 Fasting      75 TRUE     
14 2024-07-12 Breakfast    91 TRUE     
15 2024-07-12 Lunch        NA NA       
16 2024-07-12 Dinner       NA NA       

需求

需创建瓷砖图(tile plot),基于threshold实现两种填充渐变:

  • threshold为FALSE时,value越高填充越红;
  • threshold为TRUE时,value越低填充越绿;
  • threshold为NA时用灰色(默认颜色)。

尝试代码

library(ggplot2) 

ggplot(dat, aes(x = meal, y = Date, fill = threshold)) +
  geom_tile() +
  geom_text(aes(label = value), color = "white", fontface = "bold") +
  scale_fill_manual(values = c("#ef5350", "#48bf53")) +
  scale_x_discrete(expand = c(0, 0)) +
  scale_y_date(expand = c(0, 0), date_breaks = "1 day", date_labels = "%B %d") +
  theme(legend.position = "none") +
  labs(x = element_blank(), y = element_blank())

当前输出仅为纯色块,无法在threshold分组内实现基于value的渐变效果,需解决该问题。

解决方案

要实现分组渐变,需将value按threshold分组归一化,再映射到对应颜色区间,具体代码如下:

library(ggplot2)
library(dplyr)
library(scales)

# 预处理数据:按threshold分组标准化value到0-1区间
dat_processed <- dat %>%
  group_by(threshold) %>%
  mutate(norm_value = ifelse(is.na(threshold), NA, rescale(value))) %>%
  ungroup()

# 绘制渐变瓷砖图
ggplot(dat_processed, aes(x = meal, y = Date)) +
  geom_tile(aes(fill = interaction(threshold, norm_value)), color = "white") +
  geom_text(aes(label = value), color = "white", fontface = "bold") +
  # 自定义颜色映射
  scale_fill_manual(
    values = c(
      # TRUE组:value越低(norm_value越接近0)颜色越深绿
      gradient_n_pal(c("#2e7d32", "#c8e6c9"))(seq(0, 1, length.out = 10)),
      # FALSE组:value越高(norm_value越接近1)颜色越深红
      gradient_n_pal(c("#ffccbc", "#c62828"))(seq(0, 1, length.out = 10)),
      # NA值填充灰色
      "grey80"
    ),
    guide = "none"
  ) +
  scale_x_discrete(expand = c(0, 0)) +
  scale_y_date(expand = c(0, 0), date_breaks = "1 day", date_labels = "%B %d") +
  theme_minimal() +
  labs(x = NULL, y = NULL)

代码说明

  • 数据归一化:用rescale()将每个threshold分组内的value缩放到0-1范围,确保每组数值都能覆盖完整渐变区间。
  • 颜色逻辑:
    • threshold=TRUE组:从深绿到浅绿渐变,对应value从低到高;
    • threshold=FALSE组:从浅红到深红渐变,对应value从低到高,满足"值越高越红"的需求;
    • NA值直接指定灰色填充。
  • 交互变量:用interaction(threshold, norm_value)作为填充变量,让ggplot区分不同分组的归一化数值,从而应用对应渐变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 22:32:01