Frank Harrell Frank Harrell - 1 year ago 162
R Question

How to get R plotly to use different colors for different line segments

I can get the following to work if

is a
variable but I would like colors treated continuously. When I run the following, the color is ignored - line segments are all blue.

x <- rep(c(1, 1, NA, 2, 2, NA, 3, 3, NA), 2)
y <- c(1, 2, NA, 2, 3, NA, 3, 4, NA, 11, 12, NA, 12, 13, NA, 13, 14, NA)
g <- c(rep(1, 9), rep(2, 9))
plot_ly(x=x, y=y, type='lines', color=g)

There is a solution using
but I'd rather find an all-

g <- ggplot(data) + geom_segment(aes(x=x, xend=x2, y=y, yend=y2, color=z)

Answer Source

While plotly seems to have quite a bit of support for mapping colors to markers, it appears to have very little for lines so you have to supply that. The following sets up a mapping between a palette and the values of g and then creates a plotly object with line colors and a color bar corresponding to the mapping to the palette.

  df <- data.frame(x=x, y=y, g=g)
#  Seclect a color palette from the ColorBrewer palettes
   num_colors <- 8
   color_pal <- brewer.pal(num_colors, "RdYlBu")
#  Make a plotly colorscale for the palette  
   g_colorscale <- data.frame( seq(0,1, 1/(num_colors-1)), color_pal)
   colnames(g_colorscale) <- NULL
#  Set the min and max for mapping g values to colors    
   gmin <- min(df$g)-.5
   gmax <- max(df$g)+.5
#  Create an interpolation function for mapping g values to colors 
   color_rmp <- colorRamp(color_pal)
   g_color_map <- function(g, gmin,  gmax) {
                        g_3color <- as.vector(color_rmp((g - gmin)/(gmax-gmin)))/255 
                        rgb(g_3color[1],g_3color[2], g_3color[3]) 
# Create plotly object with a colorbar    
  sp <- plot_ly(data=df, x=x, y=y, type="scatter", mode="markers", 
                             cmin=gmin, cmax=gmax , size=1))
# Add a line for each g value
  for( g_line in unique(df$g)) {
    sp <- add_trace(sp, data=df[df$g==g_line,], x=x, y=y, 
                   type="scatter", mode="lines", inherit=FALSE, showlegend=FALSE,
                   name=g_line, evaluate=TRUE, 
                   line=list(width=5, dash="solid",
                             color=g_color_map(g_line, gmin=gmin, gmax=gmax)))
# Add chart features  
  sp <- layout(sp, xaxis = list(range=c(.5,3.5)))

which give the chart

enter image description here

My impression is that plotly is a lower level plotting package and that, for more complex charts, it's probably more straightforward to develop the chart in ggplot and then convert to a plotly object rather than developing directly in plotly. Comparing your ggplot solution with the native plotly approach given above is an example of this.