Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to use a different fill gradient based on value threshold in ggplot2?

Data

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       

Problem

I want to create a tile plot with two different gradients based on a threshold:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

  1. Where threshold is FALSE the higher the value the more red
  2. Where threshold is TRUE the lower the value the more green
  3. Where threshold is NA grey is fine (this is the default anyway).

Attempt

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())

Tile plot with only green and red tiles

This output is what I would like but I cannot get the gradient to work within threshold.

>Solution :

The usual trick to do this, is to map value to the alpha transparency. In your case, you just need to flip the direction for the green case first:

library(ggplot2) 

dat |> 
  mutate(
    alpha_scale = ifelse(threshold, scales::rescale(-value), scales::rescale(value)),
    .by = threshold
  ) |> 
  ggplot(aes(x = meal, y = Date, fill = threshold)) +
  geom_tile(aes(alpha = alpha_scale)) +
  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())

enter image description here

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading