Search code examples
rggplot2plotlyggplotly

Plot order of annotations changes with ggplotly


I create a bar plot using ggplot with several annotations of the form rect. I do it such that the annotations are behind the bars in the plot. When I convert the plot using ggplotly, the annotations appear in front of the bars. Is there a way that I can preserve the order of plotting using ggplotly? Or can I change the order after the ggplotly conversion?

name = c("Phil", "Ian", "Leslie", "Darla", "Silvia", "Ron", "Emily", "Jack")
score = c(10, 12, 15, 30, 35, 40, 55.2, 75)
test1 <- data.frame(name, score)

library(ggplot2)
library(plotly)

plt <- ggplot(test1, aes(x=name, y=score)) +
  
  scale_x_discrete() +
  
  annotate("rect", xmin=0, xmax=9, ymin=0, ymax=20, fill="#2eb82e", alpha=0.4) +
  annotate("rect", xmin=0, xmax=9, ymin=20, ymax=50, fill="#ff0000", alpha=0.4) +
  
  geom_bar(stat="identity")

ggplotly(plt)

Desired behaviour using ggplot Desired behaviour using ggplot

Plotting order changes when converted using ggplotly Plotting order changes when converted using ggplotly


Solution

  • I found a solution in the end that still creates plot in ggplot but adds the shapes after the fact using plotly by manually editing the plotly_plot structure. I would still prefer it if I could do it all in ggplot but I think that it isn't possible when converting with ggplotly:

    library(ggplot2)
    library(plotly)
    
    name = c("Phil", "Ian", "Leslie", "Darla", "Silvia", "Ron", "Emily", "Jack")
    score = c(10, 12, 15, 30, 35, 40, 55.2, 75)
    test1 <- data.frame(name, score)
    
    plt <- ggplot() +
      geom_bar(data=test1, aes(x=name, y=score), stat="identity")
    
    plotly_plot <- ggplotly(plt)
    
    # Turn off the grid or else it shows over the top of the 
    plotly_obj$x$layout$xaxis$showgrid <- FALSE
    plotly_obj$x$layout$yaxis$showgrid <- FALSE
    
    # Add the shapes to the plotly object
    plotly_obj$x$layout$shapes <- list(list(type = 'rect', 
                                            x0 = 0, x1 = 9, xref = "x", 
                                            y0 = 0, y1 = 20, yref = "y", 
                                            fillcolor = "#2eb82e", 
                                            opacity  = 0.4,
                                            layer = 'below'),
                                       list(type = 'rect', 
                                            x0 = 0, x1 = 9, xref = "x", 
                                            y0 = 20, y1 = 50, yref = "y",
                                            fillcolor = "#ff0000", 
                                            opacity  = 0.4,
                                            layer = 'below'))
    
    # Make the line colours the same as the fill colour...there must be a simple way to add this to the code above as well.
    plotly_obj$x$layout$shapes[[1]]$line$color <- "#2eb82e"
    plotly_obj$x$layout$shapes[[2]]$line$color <- "#ff0000"
    
    plotly_obj