I'm trying to make a heatmap in plotly with a binned colorbar with assigned colors to represent a categorical variable in my data.
I assigned the categories to numbers to make it continous for the heatmap, and then I thought I could use tickvals to label the numbers as their categorical variable. I'm close but the color scale I've created doesn't seem to work as an array. I want the colorbar in the legend to be the 5 discrete colors in colors_df. I've looked at some other examples in stackoverflow but I can't see why mine isn't working based on the code in the solutions of those posts (for example).
colors_df <- structure(list(
c(0.99, 1.99, 1.99, 2.99, 2.99, 3.99, 3.99, 4.99, 4.99, 5.99),
c("#65B32E", "#65B32E", "#7CBDC4", "#7CBDC4", "#C0D236", "#C0D236", "#3E5B84", "#3E5B84", "#008C75", "#008C75")),
class = "data.frame",
row.names = c(NA, 10L))
values <- letters[1:5]
df <- data.frame(a = LETTERS[1:5], b = month.abb[1:5]) %>%
complete(a,b) %>%
mutate(c = sample(values, 25, replace = T)) %>%
mutate(continuousc = as.numeric(factor(c, levels = values, labels = 1:length(values))))
plot_ly(
data = df,
x = ~b,
y = ~a,
z = ~continuousc,
ygap = 2,
xgap = 2,
type = "heatmap",
colorscale=colors_df,
colorbar = list(
tickmode="array",
tickvals=1:5,
ticktext=values,
len=0.5))
UPDATE
I figured out a solution that works, though I can't figure out how to assign a color to null values (if possible) - any recommendations?
library(tidyverse)
library(plotly)
library(RColorBrewer)
n_values <- 7
values <- c(letters[1:n_values], NA)
scale_step <- 1/n_values
cols <- brewer.pal(n_values, "RdYlBu")
# scales::show_col(cols)
df <- data.frame(a = LETTERS[1:n_values], b = month.abb[1:n_values]) %>%
complete(a,b) %>%
mutate(c = sample(values, n_values * n_values, replace = T)) %>%
mutate(continuousc = as.numeric(factor(c, levels = values, labels = 1:n_values)))
cdf <- structure(list(
sort(c(seq(0, 1, scale_step), seq(scale_step, 1-scale_step, scale_step))),
rep(cols, each=2)),
row.names = c(NA,-n_values*2L), class = "data.frame")
tickvalues <- seq(1 +(n_values-1)/n_values/2, n_values - (n_values-1)/n_values/2, (n_values-1)/n_values/2)
tickvalues <- tickvalues[seq(1, length(tickvalues), 2)]
plot_ly(data = df,
x = ~b,
y = ~a,
z = ~continuousc,
customdata = ~c,
ygap = 2,
xgap = 2,
type = "heatmap",
colorscale=cdf,
hovertemplate=paste(
'<b>a</b>: %{y}',
'<br><b>b</b>: %{x}',
'<br><b>c</b>: %{customdata}<extra></extra>'),
colorbar = list(
tickmode="array",
tickvals=tickvalues,
ticktext=values,
len=0.5))