Search code examples
rggplot2plotlyggplotly

ggplotly with geom_ribbon grouping


I'm having some problems in converting a ggplot in to a plotly object, and retaining the same legend attributes. What I want:

  • For grouped series, a single line for fit, and faded region for ribbon of same colour, with transparency
  • No lines at the edge of the ribbon
  • Grouped legends for the lines, points and ribbons

Here is the code showing the 2 approaches I tried based on this answer: ggplot: remove lines at ribbon edges

Both have an undesirable effect as you can see when running. Any suggestions would be great :)

library(plotly)
library(ggplot2)
# fake data
set.seed(1)
dt <- data.frame(x=rep(1:7,2), group=rep(letters[1:2], each=7), value=runif(14))
dt$lwr <- dt$value*.9
dt$upr <- dt$value*1.1

# build plot in ggplot, don't want lines at the edge
pl <- ggplot(data=dt, aes(y=value, x=x, group=group, colour=group,
                          fill=group)) +
  geom_point() +
  geom_line() +
  geom_ribbon(aes(ymin=lwr, ymax=upr), alpha=.3, linetype=0) +
  theme_minimal()

# looks ok, no lines at the edges
pl

# lines at edges, single group
ggplotly(pl)

# alternative: try reverting colour to NA
pl2 <- ggplot(data=dt, aes(y=value, x=x, group=group, colour=group,
                          fill=group)) +
  geom_point() +
  geom_line() +
  geom_ribbon(aes(ymin=lwr, ymax=upr), alpha=.3, colour=NA) +
  theme_minimal()

# looks ok
pl2

# no lines, but now not grouped, and some weird naming
ggplotly(pl2)

Thanks, Jonny

EDIT: Addition to the accepted answer, in functional form

# dd: ggplotly object
library(stringi)
library(rvest)
remove_ggplotly_ribbon_lines <- function(dd){
  find <- rvest::pluck(dd$x$data, "fillcolor")
  w <- which(!sapply(find, is.null))
  for(i in w){
    dd$x$data[[i]]$line$color <- 
      stringi::stri_replace_all_regex(dd$x$data[[i]]$line$color, ",[\\d.]*\\)$", ",0.0)")
  }
  return(dd)
}
remove_ggplotly_ribbon_lines(ggplotly(pl))

Solution

  • Hi this is more a comment than an answer but I do not have right to post comments.

    If you investigate the ggplotly object you will see that it is actually just a list. Changing the right elements of the list helps in controlling plot options.

    The solution below just changes the alpha of the lines at ribbon edges. Hope this helps

    library(plotly)
    
    set.seed(1)
    dt <- data.frame(x=rep(1:7,2), group=rep(letters[1:2], each=7), value=runif(14))
    dt$lwr <- dt$value*.9
    dt$upr <- dt$value*1.1
    
    # build plot in ggplot, don't want lines at the edge
    pl <- ggplot(data=dt, aes(y=value, x=x, group=group, colour=group,
                          fill=group)) +
    geom_point() +
    geom_line() +
    geom_ribbon(aes(ymin=lwr, ymax=upr), alpha=.3, linetype=0) +
    theme_minimal()
    
    # looks ok, no lines at the edges
    pl
    
    # no lines at edges
    dd = ggplotly(pl)
    dd$x$data[[3]]$line$color = "rgba(248,118,109,0.0)"
    dd$x$data[[4]]$line$color = "rgba(0,191,196,0.0)"
    dd
    

    enter image description here