2

I'm trying to fill the background of a ggplot line graph to indicate day/night periods. The method in this answer works great, but I want to display them interactively using ggplotly, and that becomes a problem because of this bug, where ggplotly doesn't like -Inf and Inf used as the y limits for geom_rect. Does anyone know of a workaround that will work with ggplotly?

For the sake of readability, I've pasted the example code from the other answer in here:

library(ggplot2)
dat <- data.frame(x = 1:100, y = cumsum(rnorm(100)))
#Breaks for background rectangles
rects <- data.frame(xstart = seq(0,80,20), xend = seq(20,100,20), col = letters[1:5])

p <- ggplot() + 
  geom_rect(data = rects, aes(xmin = xstart, xmax = xend, ymin = -Inf, ymax = Inf, fill = col), alpha = 0.4) +
  geom_line(data = dat, aes(x,y))
p

produces this lovely figure: ggplot line graph with filled background

However, if you do this:

ggplotly(p)

You lose the background fills: enter image description here

Luther Blissett
  • 373
  • 1
  • 10
  • This doesn't produce the exact same result where the coloured rectangles reach all the way to the top and bottom but you could use the following: Replace `ymin` and `ymax` `+/- Inf` arguments by `min(dat$y)` and `max(dat$x)` as a workaround. This way the colours will definitely cover all of your `geom_line`, just not reach to the very outside of the plotting area. – juljo Sep 18 '20 at 08:20

1 Answers1

5

As juljo mentioned in his comment, the issue is the rectangles' y-range.

To resolve this issue:

  • Plot your data first

    library(ggplot2)
    library(plotly) 
    dat <- data.frame(x = 1:100, y = cumsum(rnorm(100)))
    
    #Breaks for background rectangles
    rects <- data.frame(xstart = seq(0,80,20), xend = seq(20,100,20), col = letters[1:5])
    
    # Only plot the data
    p <- ggplot() + 
        geom_line(data = dat, aes(x,y))
    
  • Get the y-range of the plot

        ylims = ggplot_build(p)$layout$panel_params[[1]]$y.range
    
  • Use the y-range to create the rectangles and add them to the plot

        p = p + 
            geom_rect(data = rects, aes(xmin = xstart, xmax = xend, ymin = ylims[1], ymax = ylims[2], fill = col), alpha = 0.4)
    

p:

enter image description here

ggplotly(p):

enter image description here

Aziz
  • 20,065
  • 8
  • 63
  • 69