如何保存在一个闪亮的应用程序中制作的情节

我试图找出如何使用下载按钮,以保存一个情节与闪亮。包中的示例演示了 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工作没有错误,但它不写的图形。

如果您能提供任何关于如何使用 Handler 编写情节的技巧,我们将不胜感激。

57656 次浏览

I didn't manage to make it work with ggsave, but with a standard call to png() it seems to be okay.

I only changed the output$downloadPlot part of your server.R file :

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

Note that I had some problems with the 0.3 version of shiny, but it works with the latest from Github :

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

Here's a solution that allows using ggsave for saving shiny plots. It uses a logical checkbox and text input to call ggsave(). Add this to the ui.R file inside sidebarPanel:

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

Then add this to the server.R file instead of the current output$plot reactivePlot function:

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

A user can then type the desired filename in the textbox (without extension) and tick the checkbox to save in the app directory. Unchecking the box prints the plot again. I'm sure there are neater ways of doing this, but at least I can now use ggsave and cairo in windows for much nicer png graphics.

Please add any suggestions you may have.

Not sure if this question is still active but it's the first one that came up when searching for "saving plots in shiny app" so I wanted to quickly add how to get ggsave to work with downloadHandler along the lines of the original question.

The alternative strategies suggested by juba using direct output instead of ggsave and alternative strategy suggested by alexwhan himself both work great, this is just for those who absolutely want to use ggsave in the downloadHandler).

The problem reported by alexwhan is caused by ggsave trying to match the file extension to the correct graphics device. The temporary file, however, doesn't have an extension so the matching fails. This can be remedied by specifically setting the device in the ggsave function call, like so in the original code example (for a 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)
}
)

This call basically takes the device function for a png that ggsave assigns internally (you can look at the ggsave function code to see the syntax for jpg, pdf, etc). Perhaps, ideally, one could specify the file extension (if different from the file name - as is the case here for the temporary file) as a ggsave parameter but this option is currently not available in ggsave.


A minimal self-contained working example:

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

Update

As of ggplot2 version 2.0.0, the ggsave function supports character input for the device parameter, that means the temporary file created by the downloadHandler can now be saved with a direct call to ggsave by specifying that the extension to be used should be e.g. "pdf" (rather than passing in a device function). This simplifies the above example to the following

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

This is old, but still the top hit when someone googles "R shiny save ggplot", so I will contribute another workaround. Very simple... call ggsave in the same function that displays your graph, which will save the graph as a file on the server.

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

Then, use downloadHandler and use file.copy() to write data from the existing file to the "file" parameter.

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

Works for me.