光沢のあるアプリで作成されたプロットを保存する


85

downloadButtonを使用して光沢のあるプロットを保存する方法を理解しようとしています。パッケージの例は、.csvを保存するためのdownloadButton / downloadHandlerを示しています。それに基づいて再現可能な例を作ります。

ために 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.Rおよび作業ディレクトリ内のserver.Rフォルダー(foo)に保存します。光沢のあるアプリを実行するには、を実行しrunApp("foo")ます。

を使用するとggsave、ggsaveがfilename関数を使用できないことを示すエラーメッセージが表示されます(私は思います)。標準のグラフィックデバイス(以下のような)を使用するとDownload Plot、エラーなしで動作しますが、グラフィックは書き込まれません。

プロットを書くためにdownloadHandlerを機能させるためのヒントをいただければ幸いです。

回答:


69

この質問がまだアクティブかどうかはわかりませんが、「光沢のあるアプリでプロットを保存する」を検索したときに最初に出てきた質問なので、元の質問に沿ってggsaveをdownloadHandlerで動作させる方法をすばやく追加したいと思いました。

ggsaveの代わりに直接出力を使用するjubaによって提案された代替戦略と、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ための機能をpngそのggsave内部で割り当て(あなたが見ることができる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使用する拡張子を"pdf"(渡すのではなく)などに指定することで、を直接呼び出すことで保存できるようになりました。デバイス機能で)。これにより、上記の例が次のように簡略化されます。

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

1
私はあなたの答えが実際にここで正しいものであると信じています。ggsave(file, plotInput(), device = png)デバイス(ラッパー)関数を作成する代わりに使用することもできます。
Yihui Xie

@sebkopfその間の年と少しであなたの答えを逃しました!
alexwhan 2014

1
@Yihuiこのソリューションは私には機能しません:Rバージョン3.1.0、ggplot2_1.0.0shiny_0.10.1。保存ボックスがポップアップし、[保存]をクリックしますが、ファイルは保存されません。誰でも確認できますか?
zx8754 2014

3
@ zx8754答えに完全な例を追加しました。RStudioビューアにはファイルをダウンロードできないという既知のバグがあるため、RStudioで表示するのではなく、Webブラウザで実行する必要があることに注意してください。
Yihui Xie

1
@sebkopfはい、実際の例を試した後で気付いたので、ここでの最初のコメントは実際には間違っていました。説明してくれてありがとう!
Yihui Xie

24

これは、光沢のあるプロットを保存するためにggsaveを使用できるようにするソリューションです。論理チェックボックスとテキスト入力を使用してを呼び出しますggsave()。これをui.R内部のファイルに追加しますsidebarPanel

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

次にserver.R、現在のoutput$plotreactivePlot関数の代わりにこれをファイルに追加します。

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グラフィックを作成できます。

あなたが持っているかもしれない提案を追加してください。


isolate周りにブロックがない場合input$filenamefilenameテキストボックスを変更すると、チェックボックスがオンになっている場合にもファイルの保存が求められます。
jpd527 2014

23

私はそれをうまく動作させることができませんでしたがggsave、それへの標準的な呼び出しpng()では大丈夫のようです。

output$downloadPlotはあなたのserver.Rファイルの一部だけを変更しました:

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

0.3バージョンのshinyで問題が発生しましたが、Githubの最新バージョンで動作することに注意してください。

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

OK、downloadHandlerの処理のこの段階では、ggsaveが機能しないことを受け入れます。光沢のある0.3はdownloadHandlerで崩壊します、その通りです。ggsaveが機能することを可能にするdownloadHandlerを回避することを考え出した代替ソリューションを投稿します。
alexwhan 2013

1
@juba同様の(ggplot2以外の)メソッドでPDFに出力しようとする試みが機能しない理由はありますか?開いていない壊れたPDFが表示されます。plotInputは、プロットオブジェクトの代わりにプロットを配信できませんか?
地理理論2014

20

これは古いですが、誰かが「R shiny save ggplot」をグーグルで検索すると、依然としてトップヒットになるので、別の回避策を提供します。非常に簡単です...グラフを表示するのと同じ関数でggsaveを呼び出すと、グラフがファイルとしてサーバーに保存されます。

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

次に、downloadHandlerを使用file.copy()し、を使用して既存のファイルから「file」パラメーターにデータを書き込みます。

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

私のために働きます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.