问题
I currently have a Plotly heatmap with categorical axes.
The heat map plots the individuals of a graph against themselves, with each pair of individuals having a integer value (the z-value, which is what is plotted on the heat map) assigned to that pair (it's a measure of how fair apart the pair our). Right now, the colors on the heat map are being automatically assigned.
Unfortunately, I can't quite figure out how to specify the color scheme for such a heat map. Is it possible to specify the colors that are used for each z-value? For example, could I set 1 = blue, 2 = red, 3 = green, etc. ?
回答1:
I had exactly the same problem and I managed to figure it out with some small hacks. This question seem the most relevant to post the answer. As for now, Plotly won't let you do that explicitly, that is to specify exact colors to categorical (discrete) heatmap values. This is documented in this github issue. A pure JS solution is linked there and it took me a while to reproduce it in R (using Plotly 4.7.1).
First, instead of one matrix holding all the data, you need to have one matrix per category, each filled with ones and NA's. Each matrix must be the same size. Let's make up some data.
greenSeriesData <- matrix(c(1,1,NA,NA,1,NA,NA,NA,1), nrow = 3)
redSeriesData <- matrix(c(NA,NA,1,1,NA,NA,NA,NA,NA), nrow = 3)
blueSeriesData <- matrix(c(NA,NA,NA,NA,NA,1,1,1,NA), nrow = 3)
Then for each category you need to have a separate data.frame holding color for given category. What's important is that those data.frames needs to have no colnames.
greenColor <- data.frame(x = c(0,1), y = c("#63a803", "#63a803"))
colnames(greenColor) <- NULL
redColor <- data.frame(x = c(0,1), y = c("#a80b03", "#a80b03"))
colnames(redColor) <- NULL
blueColor <- data.frame(x = c(0,1), y = c("#035da8", "#035da8"))
colnames(blueColor) <- NULL
And you're ready to plot specifying each category as a separate trace:
plot_ly(
type = "heatmap"
) %>% add_trace(
z = greenSeriesData,
colorscale = greenColor
) %>% add_trace(
z = redSeriesData,
colorscale = redColor
) %>% add_trace(
z = blueSeriesData,
colorscale = blueColor
)
If you want to further adjust the legend to look good, you would need to add a colorbar
argument to each trace:
plot_ly(
type = "heatmap"
) %>% add_trace(
z = greenSeriesData,
colorscale = greenColor,
colorbar = list(
len = 0.3,
y = 1,
yanchor = 'top',
title = 'Green series',
tickvals = ''
)
) %>% add_trace(
z = redSeriesData,
colorscale = redColor,
colorbar = list(
len = 0.3,
y = 1,
yanchor = 'top',
title = 'Red series',
tickvals = ''
)
) %>% add_trace(
z = blueSeriesData,
colorscale = blueColor,
colorbar = list(
len = 0.3,
y = 1,
yanchor = 'top',
title = 'Blue series',
tickvals = ''
)
)
回答2:
I had the same issue and got here through the github link mentioned by Mikolaj. A second simplified approach that worked for me was to define colorscale
manually and get rid of the legend (one can draw it manually).
For the sake of simplicity, let's take three categories (colors).
colors <- RColorBrewer::brewer.pal(3, 'Set2')
The colorscale
is defined with respect to normalized values, so one can simply do in this case:
colorscale <- list(
list(0, colors[1]),
list(0.5, colors[2]),
list(1, colors[3])
)
This can be generalized for N colors defining the first values in the nested lists as (i - 1)/(N - 1)
, where i is the respective color
index.
For example:
plot_ly() %>%
add_trace(
type = "heatmap",
data = mtcars %>%
group_by(cyl, gear) %>%
summarise(n = n()) %>%
mutate(cat = 1 + (n > 1) + (n > 10)),
x = ~cyl,
y = ~gear,
z = ~cat,
colorscale = colorscale,
showscale = FALSE
)
来源:https://stackoverflow.com/questions/44861851/specifying-the-colors-in-a-plotly-heatmap