I am working with survey data where a person responds from 'not' to 'absolutely' in response to being asked whether one variable affects another. The responses are mapped to numbers, and a mean response is calculated.
I am presenting these mean values in a heatmap (x and y are lists with the same variable names). I would like the colour of squares in the heatmap to reflect the numerical mean, but I would like the labels on the colorbar to reflect the actual response text (e.g. 'not', 'lowly, 'moderately', 'highly', 'very highly') and to limit the tick marks to positions 0,1,2,3,4.
I'm not sure this can be done with plotly. I was able to do it with ggiraph, but this is going into Shiny and ggiraph has its own issues there - in plotly I have more control over display size and I couldn't get ggiraph to render large enough.
Minimal code is below, and so is the output.
library(plotly)
library(tidyr)
M <- matrix(c(NA, 1,3, 2, NA, 4, 3, 0, NA), nrow = 3, ncol = 3)
names_M <- c('var1', 'var2', 'var3')
val_to_char <- function(x) {
if(is.na(x)) {return(x)}
else if(x < 0.5) {return('not')}
else if(x < 1.5) {return('lowly')}
else if(x < 2.5) {return('moderately')}
else if(x < 3.5) {return('highly')}
else {return('very high')}
}
labels <- apply(M, c(1,2), val_to_char)
fig <- plot_ly()
fig <- fig %>%
add_trace(
type = 'heatmap',
x = names_M, y = names_M, z = M, text = labels,
hovertemplate = '<extra></extra> Row: %{y}</br></br>Col: %{x}</br>Avg response: %{text}'
)
fig
You could use ggplot
and ggplotly
for more flexibility. But you first need to tranform your data into long data.frame:
M <- as.data.frame.matrix(matrix(c(NA, 1,3, 2, NA, 4, 3, 0, NA), nrow = 3, ncol = 3))
names(M) <- c('var1', 'var2', 'var3')
p <- M %>%
pivot_longer(.,paste0("var",1:3),names_to = "x",values_to = "z") %>%
mutate(y = rep(paste0("var",1:3),each = 3)) %>%
ggplot(aes(x,y,fill = z))+
geom_tile() +
scale_fill_continuous(breaks = 0:4,labels = c("not","lowly","moderatly","highly","very high"))
ggplotly(p)
The function scale_fill_continuous
allows you to specify manually your labels for different breaks. You have a lot of possibilities to tweak your graph with ggplot