rcolorsplotlyheatmap

Using two separate custom color scales in a heatmap in R plotly


I've been trying to make a heatmap with different color scales for the upper and lower triangles, but I can't get it to work with anything other than the built-in named color scales. If I try to use a self-defined color scale, the first one is just repeated. I feel like I must be doing something wrong but the documentation is not easy to figure out for this argument. I have seen examples on here of doing this with matrix data, but I'm not sure how to translate that to the kind of data I have here.

Here's an example of what I mean. If it's done with named colorscales (e.g., 'Viridis' and 'Cividis'), it seems to work just fine:

library(tidyverse)
library(plotly)

# generate some sample data (somewhat clunkily)
# x and y column are all unique combinations of the words "one" through "four"
# v1 and v2 columns contain random data with different ranges
f <- combn(c("one","two","three","four"),2) %>%
  t() %>%
  as.data.frame() %>%
  rename(x=1,y=2) %>%
  mutate(v1 = rnorm(n(),5), v2 = rnorm(n(), 200, sd=55)) %>%
  arrange(x,y) %>%
  mutate(
    x = factor(x,c("one","two","three","four")),
    y = factor(y,c("four","three","two","one"))
  )

# plot the heatmap with v1 in the lower triangle and v2 in the upper triangle
# use 'Viridis' and 'Cividis' as colorscales
# this works as expected!
f %>%
  plot_ly(
    x = ~x, 
    y = ~y, 
    z = ~v1, 
    colorscale = "Viridis",
    type = "heatmap"
  ) %>% 
  add_trace(
    type="heatmap",
    x = ~y,
    y = ~x,
    colorscale = "Cividis",
    z = ~v2
  )

The plot looks like I want it to:

Image

However, if I try to define my own color scales, the first one is just repeated:

# create two scales: one that goes from black to red
# and one that goes from white to green
# (it's still not 100% clear to me how this is supposed to be defined)

lwr_scale <- list(list(0,"black"),list(1,"red"))
upr_scale <- list(list(0,"white"),list(1,"green"))

# try to plot it with these two scales
# only the black to red scale is used!
f %>%
  plot_ly(
    x = ~x, 
    y = ~y, 
    z = ~v1, 
    colorscale = lwr_scale,
    type = "heatmap"
  ) %>% 
  add_trace(
    type="heatmap",
    x = ~y,
    y = ~x,
    colorscale = upr_scale,
    z = ~v2
  )

Image

I notice that the color bars all show both v1 and v2. Clearly there's something being crossed or reused but I can't tell what or why.

Can anyone help point me in the right direction? Thanks!


Solution

  • Adding both heatmaps as separate traces to a blank plot_ly object should do the trick. Using your example data:

    f %>%
      plot_ly() %>% 
      add_trace(
        type = "heatmap",
        x = ~x,
        y = ~y,
        z = ~v1,
        colorscale = lwr_scale
      ) %>%
      add_trace(
        type="heatmap",
        x = ~y,
        y = ~x,
        colorscale = upr_scale,
        z = ~v2
      )
    
    
    

    Heatmap with separate colorscale per triangle