2

I'm wondering if it's possible to convert a plotly object to a ggplot2 object in R? I have a plot object of class plotly htmlwidget.

I've tried the as.ggplot() function from the ggplotify package, but get the following error

Error in UseMethod("as.grob") : no applicable method for 'as.grob' applied to an object of class "c('plotly', 'htmlwidget')"

Is anyone aware of any alternative methods?

Background: I'm trying to arrange multiple Sankey diagrams into a single plot (e.g., using grid.arrange()). There's another question that suggests using Rshiny, but I'm wondering if it'd be possible to convert to a static ggplot object instead.

Here's a reproducible example:

  library(plotly)
  library(ggplotify)
  p <- plot_ly(
    type = "sankey",
    orientation = "h",
    width = 600,
    height = 400,

    node = list(
      label = c(c('A','B'), c('A','B')),
      pad = 15,
      thickness = 20,
      line = list(
        color = "black",
        width = 0.5
      )
    ),

    link = list(
      source = c(0,1,0,1),
      target = c(2,2,3,3),
      value =  c(1,2,3,4)
    )
  )
  class(p)
  as.ggplot(p)
massisenergy
  • 1,764
  • 3
  • 14
  • 25
Tim Williams
  • 183
  • 1
  • 10

2 Answers2

3

You don't need to convert to ggplot2 to arrange your plotly objects. Instead, the plotly package has a very nice and customizable subplot() function for you to use. Like:

p <- subplot(p1, p2, p3, p4, nrows = 2)

The function can arrange the plots in any fashion you like, I suggest you check out the gallery online for ideas:

https://plot.ly/r/subplot-charts/

But to answer your question, no, there is no way to convert a plotly object to a ggplot2 one.

josephjscheidt
  • 326
  • 1
  • 6
  • Thanks for the response. I tried what you suggested with the example I provided (changing the values slightly for `p2`) and the plots display on top of each other, not in separate rows: https://plot.ly/~tgwilliams/11/#/ any thoughts why this might be? – Tim Williams Aug 06 '19 at 01:21
  • OK I found out how to arrange multiple Sankey diagrams using the `subplot()` function in plotly. When defining the plot (`p` in this example), you need to add an additional `domain` key, e.g. `domain = list(x=c(0,0.45), y=c(0,1))`, which specifies the relative position of the plot in the plot window. – Tim Williams Aug 06 '19 at 01:32
  • That's strange. I wonder why it didn't make a grid like it normally does. In any case, I'm glad you found a workable solution. – josephjscheidt Aug 06 '19 at 02:10
1

It looks like the other answer has already satisfied your use case, but for completeness, here is a way to construct your sankey in ggplot, convert it to plotly for interactivity, and then be able to convert that back into ggplot (which was in the original question) using notly.

# install.packages("remotes")
# remotes::install_github("davidsjoberg/ggsankey")
library(ggsankey)
library(ggplot2)
library(plotly)
# remotes::install_github("gdmcdonald/notly")
library(notly)
library(dplyr)

df <- mtcars %>%
  make_long(cyl, vs, am, gear, carb)

sankey <- 
  ggplot(data = df, 
       mapping = aes(x = x, 
                     next_x = next_x, 
                     node = node, 
                     next_node = next_node,
                     fill = factor(node))) +
  geom_sankey() +
  theme_sankey(base_size = 16) 

plotly_sankey <- ggplotly(sankey)

plotly_sankey

ggplot_sankey <- notly(plotly_sankey)

ggplot_sankey
Gordon McDonald
  • 269
  • 2
  • 12