【问题标题】:download a plot without replotting in R shiny下载绘图而不在 R 中重新绘制
【发布时间】:2020-10-12 21:36:05
【问题描述】:

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

【问题讨论】:

    标签: r shiny


    【解决方案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没有被调用两次。

    【讨论】:

      【解决方案2】:

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

      我想通了。事实上,由于我们的应用程序中已经有一张图片 - 我们可以保存该图片。右键单击并在浏览器中选择“保存图像”。 虽然,这不是很好 - 一个下载按钮和自动下载许多情节会很不错。

      这样做:

      1. 我使用javascript获取图像URI(使用library(shinyjs),在应用程序的ui部分调用useShinyjs(),在server部分调用runjs());
      2. Javascript 出于某种原因无法在downloadHandler 中运行。因此,我必须制作运行 javascript 的 actionButton 并在 downloadButton 上模拟 .click()。我在这里学到了这个技巧: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)
      

      【讨论】:

        猜你喜欢
        • 2013-02-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-22
        • 2012-04-12
        • 1970-01-01
        • 2018-12-28
        相关资源
        最近更新 更多