2013-02-11 61 views
58

我想弄清楚如何使用downloadButton保存闪亮的阴谋。包中的示例演示了downloadButton/downloadHandler以保存.csv。我将基于此做出一个可重复的例子。保存在一个闪亮的应用程序中制作的阴谋

对于ui.R

shinyUI(pageWithSidebar(
    headerPanel('Downloading Data'), 
    sidebarPanel(
selectInput("dataset", "Choose a dataset:", 
      choices = c("rock", "pressure", "cars")), 
    downloadButton('downloadData', 'Download Data'), 
    downloadButton('downloadPlot', 'Download Plot') 
), 
    mainPanel(
    plotOutput('plot') 
) 
)) 

对于server.R

library(ggplot2) 
shinyServer(function(input, output) { 
    datasetInput <- reactive({ 
    switch(input$dataset, 
      "rock" = rock, 
      "pressure" = pressure, 
      "cars" = cars) 
    }) 

    plotInput <- reactive({ 
    df <- datasetInput() 
    p <-ggplot(df, aes_string(x=names(df)[1], y=names(df)[2])) + 
     geom_point() 
    }) 

    output$plot <- renderPlot({ 
    print(plotInput()) 
    }) 

    output$downloadData <- downloadHandler(
    filename = function() { paste(input$dataset, '.csv', sep='') }, 
    content = function(file) { 
     write.csv(datatasetInput(), file) 
    } 
) 
    output$downloadPlot <- downloadHandler(
    filename = function() { paste(input$dataset, '.png', sep='') }, 
    content = function(file) { 
     ggsave(file,plotInput()) 
    } 
) 
}) 

如果你回答这个问题,你可能熟悉这一点,但得到这个工作,保存到上述单独的脚本( ui.Rserver.R转换为工作目录中的文件夹(foo)。要运行闪亮的应用程序,请运行runApp("foo")

使用ggsave,我收到一条错误消息,指出ggsave不能使用filename函数(我认为)。如果我使用标准图形设备(如下所示),则Download Plot可以正常工作,但不会写入图形。

任何获得downloadHandler写作地块的提示将不胜感激。

回答

35

不知道这个问题是否仍然有效,但是它是第一个在搜索“在闪亮应用程序中保存情节”时出现的问题,所以我想快速添加如何让ggsave与downloadHandler一起工作题。

由juba使用直接输出而不是ggsave和替代策略建议的替代策略由alexwhan自己提出,他们都很好,这仅仅适用于那些绝对想在downloadHandler中使用ggsave的人)。

由alexwhan报告的问题是由ggsave尝试将文件扩展名匹配到正确的图形设备引起的。但是,临时文件没有扩展名,所以匹配失败。这可以通过在原始代码中例如特别设置设备在ggsave函数调用,像这样(为一个PNG)被补救:

output$downloadPlot <- downloadHandler(
    filename = function() { paste(input$dataset, '.png', sep='') }, 
    content = function(file) { 
     device <- function(..., width, height) grDevices::png(..., width = width, height = height, res = 300, units = "in") 
     ggsave(file, plot = plotInput(), device = device) 
    } 
) 

此呼叫基本上取device函数的pngggsave内部分配(您可以查看ggsave功能代码以查看jpgpdf等的语法)。也许,理想情况下,可以指定文件扩展名(如果与文件名不同 - 如临时文件的情况那样)作为ggsave参数,但此选项当前不可用于ggsave


的最小自包含工作示例:

library(shiny) 
library(ggplot2) 
runApp(list(
    ui = fluidPage(downloadButton('foo')), 
    server = function(input, output) { 
    plotInput = function() { 
     qplot(speed, dist, data = cars) 
    } 
    output$foo = downloadHandler(
     filename = 'test.png', 
     content = function(file) { 
     device <- function(..., width, height) { 
      grDevices::png(..., width = width, height = height, 
         res = 300, units = "in") 
     } 
     ggsave(file, plot = plotInput(), device = device) 
     }) 
    } 
)) 

sessionInfo() 
# R version 3.1.1 (2014-07-10) 
# Platform: x86_64-pc-linux-gnu (64-bit) 
# 
# locale: 
# [1] LC_CTYPE=en_US.UTF-8  LC_NUMERIC=C    
# [3] LC_TIME=en_US.UTF-8  LC_COLLATE=en_US.UTF-8  
# [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 
# [7] LC_PAPER=en_US.UTF-8  LC_NAME=C     
# [9] LC_ADDRESS=C    LC_TELEPHONE=C    
# [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C  
# 
# attached base packages: 
# [1] stats  graphics grDevices utils  datasets methods base  
# 
# other attached packages: 
# [1] ggplot2_1.0.0 shiny_0.10.1 
# 
# loaded via a namespace (and not attached): 
# [1] bitops_1.0-6  caTools_1.17  colorspace_1.2-4 digest_0.6.4  
# [5] formatR_1.0  grid_3.1.1  gtable_0.1.2  htmltools_0.2.6 
# [9] httpuv_1.3.0  labeling_0.2  MASS_7.3-34  munsell_0.4.2 
# [13] plyr_1.8.1  proto_0.3-10  Rcpp_0.11.2  reshape2_1.4  
# [17] RJSONIO_1.3-0 scales_0.2.4  stringr_0.6.2 tools_3.1.1  
# [21] xtable_1.7-3  

更新

作为GGPLOT2版本2.0.0,所述ggsave功能支持用于device参数字符输入,这意味着在临时由downloadHandler创建的文件现在可以通过直接调用ggsave来保存,方法是指定要使用的扩展名应该是eg "pdf"(而不是传入设备功能)。这简化了上面的例子以下

output$downloadPlot <- downloadHandler(
    filename = function() { paste(input$dataset, '.png', sep='') }, 
    content = function(file) { 
     ggsave(file, plot = plotInput(), device = "png") 
    } 
) 
+0

我相信你的答案其实是正确的。你也可以使用'ggsave(file,plotInput(),device = png)'而不是创建一个设备(包装)函数。 – 2014-08-23 16:01:49

+0

@sebkopf我在干预的一年中错过了你的答案! – alexwhan 2014-08-24 23:39:55

+1

@Yihui这个解决方案对我不起作用:R版本3.1.0,ggplot2_1.0.0 shiny_0.10.1。保存框弹出,点击保存,但没有保存文件。有人可以确认吗? – zx8754 2014-08-28 10:17:23

17

我没有设法使它与ggsave一起使用,但是通过标准呼叫png()它似乎没问题。

我只是改变了你server.R文件的output$downloadPlot部分:

output$downloadPlot <- downloadHandler(
    filename = function() { paste(input$dataset, '.png', sep='') }, 
    content = function(file) { 
     png(file) 
     print(plotInput()) 
     dev.off() 
    }) 

注意,我遇到了一些问题,与0.3版本的光泽,但它与最新从GitHub的工作原理:

library(devtools) 
install_github("shiny","rstudio") 
+0

好的,我会接受ggsave不会在downloadHandler的这个阶段进行工作。下载Handler会让闪亮的0.3崩溃,你是对的。我会发布一个替代解决方案,我想通过避免downloadHandler将允许ggsave工作。 – alexwhan 2013-02-12 21:26:00

+1

@juba任何想法为什么[这种尝试输出到PDF](https://gist.github.com/geotheory/b0c36071b7c0c2b384db)与类似的(非ggplot2)方法不起作用?我只是得到一个不能打开的pdf文件。 plotInput不能提供绘图而不是绘图对象吗? – geotheory 2014-12-03 02:52:36

20

这里有一个解决方案,允许使用ggsave来保存有光泽的地块。它使用逻辑复选框和文本输入来呼叫ggsave()。这给ui.R文件添加内部sidebarPanel

textInput('filename', "Filename"), 
checkboxInput('savePlot', "Check to save") 

然后将其添加到server.R文件,而不是当前output$plot reactivePlot功能:

output$plot <- reactivePlot(function() { 
    name <- paste0(input$filename, ".png") 
    if(input$savePlot) { 
     ggsave(name, plotInput(), type="cairo-png") 
    } 
    else print(plotInput()) 
    }) 

用户可以然后键入文本框中的所需的文件名(没有扩展名)并勾选复选框以保存在应用程序目录中。取消选中该框会再次打印该图。我确信有这样做的完美方式,但至少我现在可以在Windows中使用ggsave和cairo以获得更好的png图形。

请添加您可能有的任何建议。

+0

如果没有'input $ filename'周围的'isolate'块,那么对文件名'filename'的任何改变都会提示文件保存。 – jpd527 2014-02-03 18:17:12

13

这是老了,但还是当有人网上搜寻“R闪亮保存ggplot”,所以我将有助于另一个解决办法的最高命中。非常简单...在显示图形的相同函数中调用ggsave,它将图形保存为服务器上的文件。

output$plot <- renderPlot({ 
    ggsave("plot.pdf", plotInput()) 
    plotInput() 
}) 

然后,使用downloadHandler和使用file.copy()从现有文件中的数据写入到“文件”参数。

output$dndPlot <- downloadHandler(
    filename = function() { 
     "plot.pdf" 
    }, 
    content = function(file) { 
     file.copy("plot.pdf", file, overwrite=TRUE) 
    } 
) 

适合我。