Guarde las plots en una aplicación shiny

Estoy tratando de averiguar cómo usar downloadButton para guardar una ttwig con shiny. El ejemplo en el paquete muestra downloadButton / downloadHandler para guardar un .csv. Voy a hacer un ejemplo reproducible basado en eso.

Para 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') ) )) 

Para el 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()) } ) }) 

Si está respondiendo esta pregunta, probablemente esté familiarizado con esto, pero para que esto funcione, guarde lo anterior en scripts separados ( ui.R y server.R en una carpeta ( foo ) dentro del directorio de trabajo. aplicación, ejecute runApp("foo") .

Usando ggsave , ggsave un mensaje de error que indica que ggsave no puede usar la función de filename (creo). Si utilizo el dispositivo gráfico estándar (como a continuación), el gráfico de Download Plot funciona sin error, pero no escribe el gráfico.

Se agradecerá cualquier sugerencia para obtener downloadHandler trabajando para escribir ttwigs.

No estoy seguro de si esta pregunta aún está activa, pero es la primera que surgió cuando buscaba “guardar ttwigs en una aplicación shiny”, así que quería agregar rápidamente cómo hacer que ggsave funcione con downloadHandler siguiendo las líneas de la pregunta original.

Las estrategias alternativas sugeridas por juba usando output directo en lugar de ggsave y la estrategia alternativa sugerida por el propio alexwhan funcionan muy bien, esto es solo para aquellos que desean usar ggsave en el downloadHandler.

El problema informado por alexwhan es causado por ggsave tratando de hacer coincidir la extensión del archivo con el dispositivo gráfico correcto. Sin embargo, el archivo temporal no tiene una extensión, por lo que la coincidencia falla. Esto se puede remediar configurando específicamente el dispositivo en la ggsave función ggsave , como en el ejemplo del código original (para un 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) } ) 

Esta llamada básicamente toma la función del device para un png que ggsave asigna internamente (puede mirar el código de la función ggsave para ver la syntax para jpg , pdf , etc.). Quizás, idealmente, uno podría especificar la extensión del archivo (si es diferente del nombre del archivo, como es el caso aquí para el archivo temporal) como un parámetro ggsave pero esta opción no está disponible actualmente en ggsave .


Un ejemplo mínimo de trabajo autónomo:

 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 

Actualizar

A partir de ggplot2 versión 2.0.0, la función ggsave admite la entrada de caracteres para el parámetro del device , lo que significa que el archivo temporal creado por downloadHandler ahora se puede guardar con una llamada directa a ggsave especificando que la extensión que se utilizará debe ser, por ejemplo "pdf" (en lugar de pasar en una función de dispositivo). Esto simplifica el ejemplo anterior a lo siguiente

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

Aquí hay una solución que permite usar ggsave para guardar ttwigs shinys. Utiliza una checkbox lógica y entrada de texto para llamar a ggsave() . Agregue esto al archivo sidebarPanel dentro de sidebarPanel :

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

A continuación, agregue esto al archivo server.R lugar de la output$plot actual 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()) }) 

Un usuario puede escribir el nombre de archivo deseado en el cuadro de texto (sin extensión) y marcar la checkbox para guardar en el directorio de la aplicación. Al deseleccionar la casilla, se imprime la ttwig nuevamente. Estoy seguro de que hay formas más claras de hacerlo, pero al menos ahora puedo usar ggsave y cairo en windows para obtener gráficos png mucho más agradables.

Por favor agregue cualquier sugerencia que pueda tener.

No pude hacer que funcione con ggsave , pero con una llamada estándar a png() parece estar bien.

Solo cambié la parte de output$downloadPlot de su archivo server.R :

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

Tenga en cuenta que tuve algunos problemas con la versión 0.3 de shiny, pero funciona con la última versión de Github:

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

Esto es viejo, pero sigue siendo el mejor éxito cuando alguien busca “R shiny save ggplot”, así que contribuiré con otra solución alternativa. Muy simple … llama a ggsave en la misma función que muestra tu gráfico, que guardará el gráfico como un archivo en el servidor.

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

Luego, use downloadHandler y use file.copy() para escribir datos del archivo existente en el parámetro "archivo".

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

Funciona para mi.