2013-02-11 88 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) 
    } 
) 

適合我。