如何保存在闪亮的应用程序中制作的图
Posted
技术标签:
【中文标题】如何保存在闪亮的应用程序中制作的图【英文标题】:How to save plots that are made in a shiny app 【发布时间】:2013-01-26 10:51:34 【问题描述】:我正在尝试弄清楚如何使用 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.R
和 server.R
到工作目录中的文件夹 (foo
) 中. 要运行闪亮的应用程序,请运行runApp("foo")
。
使用ggsave
,我收到一条错误消息,指出ggsave
不能使用filename
函数(我认为)。如果我使用标准图形设备(如下所示),Download Plot
可以正常工作,但不会写入图形。
任何让 downloadHandler 工作以编写情节的提示将不胜感激。
【问题讨论】:
【参考方案1】:不确定这个问题是否仍然有效,但它是在搜索“在闪亮的应用程序中保存绘图”时出现的第一个问题,所以我想快速添加如何让 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)
)
此调用基本上将png
用于ggsave
内部分配的device
函数(您可以查看ggsave
函数代码以查看jpg
、pdf
等的语法)。也许,理想情况下,可以将文件扩展名(如果与文件名不同 - 就像这里临时文件的情况一样)指定为 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
参数的字符输入,这意味着现在可以通过直接调用 ggsave
来保存由 downloadHandler 创建的临时文件,方法是指定要使用的扩展名应该是例如"pdf"
(而不是传入设备函数)。这将上面的示例简化为以下示例
output$downloadPlot <- downloadHandler(
filename = function() paste(input$dataset, '.png', sep='') ,
content = function(file)
ggsave(file, plot = plotInput(), device = "png")
)
【讨论】:
我相信您的答案实际上是正确的。您也可以只使用ggsave(file, plotInput(), device = png)
而不是创建设备(包装器)函数。
@sebkopf 在接下来的一年里我错过了你的答案!
@Yihui 这个解决方案对我不起作用:R 版本 3.1.0,ggplot2_1.0.0 shiny_0.10.1。弹出保存框,点击保存,但没有保存文件。谁能确认一下?
@zx8754 我刚刚在答案中添加了一个完整的示例。请注意,您应该在 Web 浏览器中运行它,而不是在 RStudio 中查看它,因为 RStudio 查看器存在无法下载文件的已知错误。
@sebkopf 是的,我尝试了一个真实的例子后才意识到,所以我在这里的第一条评论实际上是错误的。感谢您的澄清!【参考方案2】:
我没有设法让它与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 版本的 Shiny 时遇到了一些问题,但它适用于 Github 的最新版本:
library(devtools)
install_github("shiny","rstudio")
【讨论】:
好的,我接受 ggsave 在这个阶段无法使用 downloadHandler。闪亮的 0.3 与 downloadHandler 分崩离析,你是对的。我将发布一个替代解决方案,我想出避免使用 downloadHandler 的方法,这将允许 ggsave 工作。 @juba 知道为什么 this attempt to output to pdf 使用类似的(非 ggplot2)方法不起作用?我只是得到一个打不开的损坏的pdf。 plotInput 可以不提供绘图而不是绘图对象吗?【参考方案3】:这是一个允许使用 ggsave 保存闪亮图的解决方案。它使用逻辑复选框和文本输入来调用ggsave()
。将此添加到sidebarPanel
内的ui.R
文件中:
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 图形。
请添加您可能有的任何建议。
【讨论】:
如果input$filename
周围没有isolate
块,如果选中该框,对filename
文本框的任何更改也会提示文件保存。【参考方案4】:
这是旧的,但当有人用谷歌搜索“R shiny save 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)
)
为我工作。
【讨论】:
这对我来说是最好的解决方案 - 谢谢!以上是关于如何保存在闪亮的应用程序中制作的图的主要内容,如果未能解决你的问题,请参考以下文章
如何在闪亮的应用程序中制作kable table reactive()?闪亮+ kable