I can use the colors
argument to provide a color palette for my plotly
chart like this:
library(plotly)
library(viridis)
col_pal <- viridis(10)
plot_ly(mtcars) %>%
add_trace(x = ~ mpg, y = ~ cyl, color = ~ factor(cyl), colors = col_pal,
type = "scatter", mode = "markers", marker = list(size = 25))
This will produce the following plot:
Using the following JavaScript
I can determine which colors are effectively used:
const cols = $('path.point').map(function() {
const style = $(this).attr('style');
const fill_col = style.match(/fill: [^;]+/g)[0].replace('fill: ', '');
const hex = '#' + fill_col
.slice(4, -1)
.split(',')
.map(x => (+x).toString(16).padStart(2, 0))
.join('');
return hex;
})
new Set(cols)
// Set(3) {'#440154', '#25908c', '#fde725'}
If I compare that to col_pal
:
col_pal
# [1] "#440154FF" "#482878FF" "#3E4A89FF" "#31688EFF" "#26828EFF" "#1F9E89FF"
# [7] "#35B779FF" "#6DCD59FF" "#B4DE2CFF" "#FDE725FF"
I see that plotly
uses the first and the last element (#440154FF
/ #FDE725FF
), and that the third color seems to be an interpolation of some sorts as it is not directly a member of col_pal
:
scales::show_col(c(col_pal[1:5], "#25908CFF", col_pal[6:10]))
My guess that the color is an interpolation of col_pal[5:6]
But I have no idea of how the color is calculated? Any ideas how I could replicate the colors plotly
uses in R knowing:
nlevels(as.factor(mtcars$cyl))
)P.S.: If my palette would contain a middle point, the color is exactly matched (change col_pal <- viridis(11)
, and the colors used are col_pal[c(1, 6, 11)]
. However, I am really interested in any combinations of oclor palette length and needed colors.
After some debugging I identified the lines in which the color mapping is done (actually already on the R side):
colScale <- scales::col_factor(pal, levels = names(pal) %||% lvls, na.color = na.color)
Thus to get exactly the colors used by plotly
we need to run:
lvls <- levels(as.factor(mtcars$cyl))
scales::col_factor(col_pal, levels = lvls)(lvls)
# [1] "#440154" "#25908C" "#FDE725"