如何使用R Shiny downloadHandler下载ggplotly图?

时间:2019-05-16 15:27:25

标签: r shiny plotly r-plotly ggplotly

我正在R中制作一个Shiny应用程序。我使用plotly使ggplots具有交互性,因此应用程序中有很多ggplotly图。我希望能够通过界面上的按钮下载每个。

我的下载按钮适用于普通ggplot对象,但不适用于ggplotly对象。一个简单的可复制示例是:

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)

该代码中注释了我尝试过的某些事情。

尝试1基于how I would normally handle plot objects in a shiny app

尝试2基于this questionthis post

尝试3基于some plotly documentation

尝试4基于this question

所有这些尝试要么下载空白的.png(尝试1),要么根本无法下载任何内容(尝试2-4)。我怀疑我不太正确地使用下载处理程序。有人对这个工作有建议吗?

编辑:在这种情况下,我需要.png文件,但是此线程上有一些很好的答案,用于下载交互式.html文件。

4 个答案:

答案 0 :(得分:1)

出于某种原因,您是否需要使用下载按钮来完成此操作?如果没有,则在模式栏中有一个单独的按钮可以下载到PNG。

enter image description here

来自https://plot.ly/r/dashboard/的仪表板。

在密谋支持论坛(https://community.plot.ly/t/remove-options-from-the-hover-toolbar/130/3)中,您可以使用config()删除其他组件。

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)
}

您还可以使用CSS移动模式栏,使其不覆盖绘图。

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

答案 1 :(得分:1)

另一种方法是使用htmlwidgets将文件另存为交互式html,以防它比png更好。

要将此html转换为静态图形,进一步的解决方法-如果出于某种原因根本不想使用plotly的打印功能-可以使用webshot保存png(这需要phantomjs)。参见下面的代码。

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

答案 2 :(得分:0)

在对Wil的答案发表评论之后,您可以按以下方式删除模式栏中不需要的按钮:

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'
         )
  )

参考文献:

答案 3 :(得分:0)

如果您希望下载具有交互功能的ggplotly图,请尝试this