下载一个没有重新绘制R情节的情节

时间:2017-01-12 16:54:46

标签: r shiny

我正在尝试下载已经绘制的ggplot图片而不再重新绘制它。我找到的所有解决方案(例如Save plots made in a shiny app)调用函数在下载图像时再次创建图形。 有解决方法吗?我的图像非常复杂,需要一些时间来创建。

2 个答案:

答案 0 :(得分:1)

使用ggplot2::last_plot功能:

library(shiny)
library(ggplot2)
k <- 0

runApp(list(
  ui = fluidPage(
    plotOutput("fooplot"),
    textOutput("fook"),
    downloadButton('foo')
    ),
  server = function(input, output) {
    plotInput = function() {
      k <<- k + 1

      qplot(speed, dist, data = cars)
    }
    output$fooplot <- renderPlot({
      plotInput()
    })

    output$fook <- renderPrint({
      k
    })

    output$foo = downloadHandler(
      filename = 'test.png',
      content = function(file) {
        device <- function(..., width, height) {
          grDevices::png(..., width = width, height = height,
                         res = 300, units = "in")
        }
        ggsave("myplot.png", plot = last_plot(), device = device)
      })
  }
))

原谅使用全局作业,只是为了表明plotInput没有被调用两次。

答案 1 :(得分:1)

这是旧线程。但是我还需要弄清楚如何避免重新使用Shiny。我的应用程序生成了很多图,并且在last_plot()中调用ggsave()并没有太大帮助。

我知道了。确实,由于我们的应用程序中已经有一个图像-我们可以保存该图像。右键单击并在浏览器中选择“保存图像”。 但是,这不是很好-下载按钮和用于下载许多地块的自动化功能会很不错。

要这样做:

  1. 我使用JavaScript获取图像URI(使用library(shinyjs),在应用程序的useShinyjs()部分中调用ui,然后在runjs()部分中调用server );
  2. 由于某种原因,JavaScript无法在downloadHandler内运行。因此,我不得不制作actionButton来运行javascript并在.click()上模拟一个downloadButton。我在这里学到了这个技巧:link
  3. 使用library(magick)从URI解码图像并保存。这是该操作的链接:link

这是示例代码:

library(shiny)
library(magick)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  #visibale action button - this button simulates click on hidden download button 
  actionButton("save_myPlot", "Download", icon = icon("download")),
  #hidden download button
  downloadButton("save_myPlot_hidden", style = "visibility: hidden;"),
  # plot
  plotOutput("myPlot")
)

server <- function(input, output, session) {
  
  #get the plot image URI and simulate click on download button
  observeEvent(input$save_myPlot, {
    shinyjs::runjs(
      "
       var p_src = document.getElementById('myPlot').childNodes[0].src; 
       Shiny.setInputValue('plot_src', p_src);
       document.getElementById('save_myPlot_hidden').click();
      "
    )
  })
  
  # downaload handler - save the image
  output$save_myPlot_hidden <- downloadHandler(
    filename = function() { 
      paste0("plot_", Sys.Date(), ".png") },
    content = function(file) {
      # get image code from URI
      plot_src <- gsub("^data.*base64,", "", input$plot_src)
      # decode the image code into the image
      plot_image <- image_read(base64_decode(plot_src))
      # save the image
      image_write(plot_image, file)
    })
  
  # plot
  output$myPlot <- renderPlot(
    plot(rnorm(5), rnorm(5))
  )
}

shinyApp(ui = ui, server = server)