Home > Net >  Set limits for scale_fill_gradientn for ratios (values from 0 to 1 with blue scale, 0 is white and v
Set limits for scale_fill_gradientn for ratios (values from 0 to 1 with blue scale, 0 is white and v

Time:08-18

I'm trying to plot different colors for my ratios in a general way (for example case/control)

For example, if we have values between 1 and 0 (which means the value of control is higher), I have a scale from white to blue. But if the value is between 1 and inf, then we have that the case is higher in value and the scale is from white to red.

I'm plotting like this:

mtcars2 <- mtcars
mtcars2$ratio1 <- mtcars$mpg / mtcars$disp
mtcars2$ratio2 <- mtcars$disp / mtcars$mpg
mtcars2$ratio3 <- mtcars$drat / mtcars$wt

a <- max(mtcars2$ratio1)

b <- ifelse(a < 2, 2, a) #so I get a value of b which is above 2 to create the scale in values


ggplot(mtcars, aes(x = rownames(mtcars), y = 1, fill = mtcars2$ratio1))  
  geom_tile()  
  theme_minimal()  
  scale_fill_gradientn(
    colours = c("blue", "white", "red"),
    na.value = "grey98",
    name = "ratio",
    values = c(0, 1, b)
  )  
  theme_classic()  
  theme(axis.text.x = element_text(
    size = 10, face = "bold", color = "black",
    angle = 45, hjust = 1
  )) #b should be always above 1 (I selected 2)


a <- max(mtcars2$ratio2)

b <- ifelse(a < 2, 2, a)


ggplot(mtcars, aes(x = rownames(mtcars), y = 1, fill = mtcars2$ratio2))  
  geom_tile()  
  theme_minimal()  
  scale_fill_gradientn(
    colours = c("blue", "white", "red"),
    na.value = "grey98",
    name = "ratio",
    values = c(0, 1, b)
  )  
  theme_classic()  
  theme(axis.text.x = element_text(
    size = 10, face = "bold", color = "black",
    angle = 45, hjust = 1
  ))


a <- max(mtcars2$ratio3)

b <- ifelse(a < 2, 2, a)


ggplot(mtcars, aes(x = rownames(mtcars), y = 1, fill = mtcars2$ratio3))  
  geom_tile()  
  theme_minimal()  
  scale_fill_gradientn(
    colours = c("blue", "white", "red"),
    na.value = "grey98",
    name = "ratio",
    values = c(0, 1, b)
  )  
  theme_classic()  
  theme(axis.text.x = element_text(
    size = 10, face = "bold", color = "black",
    angle = 45, hjust = 1
  ))

Which works fine for values between 0 and 1 (when nothing over 1 is present), but does not plot red color for values between 1 and max ratio value and when mixed values are present (between 0 and 1, and 1 and inf)

I can't consider values of log nor normalized values! I need the scale like it is

Using

a = ifelse(max(mtcars2$ratio3) > 1, max(mtcars2$ratio3), 1)

b = ifelse(max(mtcars2$ratio3) > 1, 1/max(mtcars2$ratio3), 1)

c = ifelse(b == 1, 0.99, b)
           
          

ggplot(mtcars2, aes(x = rownames(mtcars), y = 1, fill = ratio3))  
  geom_tile()  
  theme_minimal()  
  scale_fill_gradientn(
    colours = c("blue", "white", "red"),
    na.value = "grey98",
    name = "ratio",
    limits = c(0, a),
    values = c(0, c , 1)
  )  
  theme_classic()  
  theme(axis.text.x = element_text(
    size = 10, face = "bold", color = "black",
    angle = 45, hjust = 1
  ))

Works like a charm (adapted from Allan Cameron's answer)

CodePudding user response:

The values argument has to be numbers between 0 and 1 (representing the upper and lower limits of the scale), so you need something like:

ggplot(mtcars2, aes(x = rownames(mtcars), y = 1, fill = ratio3))  
  geom_tile()  
  theme_minimal()  
  scale_fill_gradientn(
    colours = c("blue", "white", "red"),
    na.value = "grey98",
    name = "ratio",
    limits = c(0, ifelse(max(mtcars2$ratio3) > 1, max(mtcars2$ratio3), 1)),
    values = c(0, ifelse(max(mtcars2$ratio3) > 1, 1/max(mtcars2$ratio3), 1), 1)
  )  
  theme_classic()  
  theme(axis.text.x = element_text(
    size = 10, face = "bold", color = "black",
    angle = 45, hjust = 1
  ))

enter image description here

CodePudding user response:

I think there are two options.

Option 1: If you want the scale to be symmetric around 1, you can set the rescaler argument of the scale to set 1 as the middle. This might work somewhat better after log-transform and setting 0 as the center.

library(ggplot2)

set.seed(0)
df <- data.frame(
  x = 1:20,
  y = 2,
  value = rlnorm(20)
)

ggplot(df, aes(x, y, fill = value))  
  geom_tile()  
  scale_fill_gradientn(
    colours=c("blue", "white", "red"), 
    na.value = "grey98", name = "ratio",
    rescaler = ~ scales::rescale_mid(.x, mid = 1)
  )

Option 2: If you don't particularly care if the scale is symmetric, you can use the values argument. I think the thing you might've overlooked in your code is that the values() should be between 0 and 1. To get the colours into that range, you need to divide by the maximum value.


ggplot(df, aes(x, y, fill = value))  
  geom_tile()  
  scale_fill_gradientn(
    colours=c("blue", "white", "red"), 
    na.value = "grey98", name = "ratio",
    values = c(0, 1, max(df$value))/max(df$value)
  )

Created on 2022-08-17 by the reprex package (v2.0.1)

  • Related