rggplot2viridis

How do I limit the range of the viridis colour scale?


I have two sets of data, which I want to present using a heat map with the viridis color scale. For the first data set, my values range from 0 to 1.2 and I can easily see the differences I want to see. However my second data set has some outliers, resulting in a range from 0 to 2. Now it's harder to see the differences in the interesting range between 0 and 1 and it's more diffucult to compare the two images directly. Is there a possibility to show the data from 0 to 1.2 using the viridis colour scale while showing the higher values in yellow ("highest" colour of the viridis scale)? Here is an example:

library(viridis)

#Create Data
DataSet1 <- expand.grid(x = 0:5, y = 0:5)
DataSet1$z <- runif(36, 0, 1.2)

DataSet2 <- expand.grid(x = 0:5, y = 0:5)
DataSet2$z <- runif(36, 0, 2)

#Plot Data
ggplot(DataSet1, aes(x, y, fill = z)) + 
  geom_tile() +
  scale_fill_viridis() +
  geom_text(aes(label = round(z, 2)), size = 2)

DataSet1: Differences between 0.5 and 0.7 are easy to see

enter image description here

ggplot(DataSet2, aes(x, y, fill = z)) + 
  geom_tile() +
  scale_fill_viridis() +
  geom_text(aes(label = round(z, 2)), size = 2)

DataSet2: Differences between 0.5 and 0.7 are diffucult to see

enter image description here


Solution

  • You can define an arbitrary rescaling function. Not sure this looks that great, would likely need some work with the legend, but in principle this mechanism allows you to map data values onto the scale in any way you want.

    ggplot(DataSet2, aes(x, y, fill = z)) + 
      geom_tile() +
      scale_fill_viridis(rescaler = function(x, to = c(0, 1), from = NULL) {
        ifelse(x<1.2, 
               scales::rescale(x,
                               to = to,
                               from = c(min(x, na.rm = TRUE), 1.2)),
               1)}) +
      geom_text(aes(label = round(z, 2)), size = 2)
    

    enter image description here