0

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!

asked Jun 26, 2025 at 0:58
0

1 Answer 1

2

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

answered Jun 26, 2025 at 8:25
Sign up to request clarification or add additional context in comments.

1 Comment

Ok, followup question: why does plotly treat the two traces like they're the same and somehow overlapping? The hovertext for both triangles say "trace 1", but the lower triangle values show up as "NaN" and the upper triangle values show their correct numeric value. I feel like this must have something to do with the fact that both colorbars show both variable names. Any ideas?

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.