17 may
2019

How to download a ggplotly plot with R Shiny downloadHandler?

I'm making a Shiny app in R. I use plotly to make my ggplots interactive, thus I have lots of ggplotly plots in the app. I would like to be able to download each one through a button on the interface.

My download button works for normal ggplot objects but not for ggplotly objects. A simple reproducible example would be:

library(shiny)
library(ggplot2)
library(processx) # for orca()
library(plotly)

ui <- fluidPage(
  mainPanel(plotlyOutput("plot1"), downloadButton('download1', 'Download Graph'))
  )

server <- function(input,output){
  make_plot1 <- function(){
    p1 = ggplot(cars, aes(x = speed, y = dist)) + geom_point()
    return(ggplotly(p1))}

  output$plot1 <- renderPlotly({ make_plot1() }) 

  output$download1 <- downloadHandler(
    filename = function() {'plot1.png'},
    content = function(file) {
      # try 1
      png(file)
      print(make_plot1())

      # try 2
      #plotly_IMAGE(make_plot1(), format = "png", out_file = file)

      # try 3
      #orca(make_plot1(), file)

      #try 4
      #export(make_plot1(), file = file)

      dev.off()
      })
  }

shinyApp(ui, server)

Some things I've tried are commented out in that code.

Try 1 is based on how I would normally handle plot objects in a shiny app

Try 2 is based on this question and this post

Try 3 is based on some plotly documentation

Try 4 is based on this question

All of these attempts either download a blank .png (try 1) or simply fail to download anything (tries 2-4). I suspect I'm not quite using the download Handler correctly. Anybody have suggestions for getting this working?

EDIT: For this case I want .png files, but there are some good answers on this thread for downloading interactive .html files.

COMENTARIOS

Stéphane Laurent

Following your comment to Wil's answer, you can remove the undesired buttons in the modebar as follows:

library(plotly)

x <- c(1:15)
y <- c(1:15)
xy <- as.data.frame(cbind(x,y))
example <- ggplot(data = xy,aes(x = x,y = y)) + geom_line()

ggplotly(example) %>% 
  config(displaylogo = FALSE,
         collaborate = FALSE,
         modeBarButtonsToRemove = list(
           'sendDataToCloud',
           'autoScale2d',
           'resetScale2d',
           'hoverClosestCartesian',
           'hoverCompareCartesian',
           'zoom2d', 
           'pan2d',
           'select2d',
           'lasso2d',
           'zoomIn2d', 
           'zoomOut2d',
           'toggleSpikelines'
         )
  )

References:

Wil

Do you need to accomplish this with a download button for some reason? If not, plotly has its own button in the modebar that downloads to a PNG.

enter image description here

Dashboard taken from https://plot.ly/r/dashboard/.

From the plotly support forum (https://community.plot.ly/t/remove-options-from-the-hover-toolbar/130/3), you can use config() to remove the other components.

make_plot1 <- function() {
  p1 = ggplot(cars, aes(x = speed, y = dist)) + geom_point()
  p1 = ggplotly(p1) %>%
    config(
      modeBarButtonsToRemove = list(
        "zoom2d",
        "pan2d",
        "zoomIn2d",
        "zoomOut2d",
        "autoScale2d",
        "resetScale2d",
        "hoverClosestCartesian",
        "hoverCompareCartesian",
        "sendDataToCloud",
        "toggleHover",
        "resetViews",
        "toggleSpikelines",
        "resetViewMapbox"
      ),
      displaylogo = FALSE
    )
  return(p1)
}

You can also move the modebar so that it doesn't cover the plot, using CSS.

.modebar {
    top: -30px !important;
}

tasasaki

If you wish to download your ggplotly graphs with interactive feature, try this.

Hellwalker

Another way would be to use htmlwidgets to save the file as an interactive html, in case that is preferable to a png.

To turn this html into a static graphic, a further workaround - if you for some reason do not want to use plotly's printing function at all - would be to save a png with webshot (which requires phantomjs). See code below.

library("shiny")
library("ggplot2")
library("data.table")
library("plotly")
library("htmlwidgets")
library("webshot")


shinyApp(

  ui = fluidPage(

    mainPanel(plotlyOutput("plot1"),
              downloadButton('download1', 'Download Graph'))
  ),

  server = function(input, output) {

    inputPlot1 <- reactive({
      p1 = ggplot(cars, aes(x = speed, y = dist)) + geom_point()
      ggplotly(p1)
    })

    output$plot1 <- renderPlotly({
      print(inputPlot1())
    })

    output$download1 <- downloadHandler(
      filename = function() {'plot1.html'},
      content = function(file) {

      htmlwidgets::saveWidget(as_widget(inputPlot1()), file)

        # Alternative using webshot with phantomjs
        # saveWidget(as_widget(inputPlot1()), "temp.html", selfcontained = FALSE)
        # webshot(url = "temp.html", file)

      }
    )

  }

) # closes shinyApp

DEJA TU COMENTARIO

© 2017 website by Rubit Corporation