Сохранить графики, сделанные в блестящем приложении
Я пытаюсь выяснить, как использовать 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
работает без ошибок, но он не пишет графику.
Приветствуются любые советы по загрузке сайта, работающего для написания графиков.
Ответы
Ответ 1
Не уверен, что этот вопрос все еще активен, но это первый, который появился при поиске "сохранения графиков в блестящем приложении", поэтому я хотел бы быстро добавить, как заставить ggsave работать с downloadHandler по строкам исходного вопроса,
Альтернативные стратегии, предложенные juba с использованием прямого вывода вместо ggsave и альтернативной стратегии, предложенной alexwhan, оба отлично работают, это просто для тех, кто абсолютно хочет использовать ggsave в downloadHandler).
Проблема, о которой сообщает 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
, чтобы увидеть синтаксис 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
Update
В версии 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")
}
)
Ответ 2
Здесь решение, которое позволяет использовать 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())
})
Затем пользователь может ввести нужное имя файла в текстовое поле (без расширения) и пометить флажок для сохранения в каталоге приложения. Снимите флажок, чтобы распечатать график. Я уверен, что есть более простые способы сделать это, но по крайней мере теперь я могу использовать ggsave и cairo в окнах для более приятной графики png.
Пожалуйста, добавьте любые предложения, которые могут быть у вас.
Ответ 3
Мне не удалось заставить его работать с 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, но она работает с последним из Github:
library(devtools)
install_github("shiny","rstudio")
Ответ 4
Это старый, но все же лучший удар, когда кто-то googles "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)
}
)
Работает для меня.
Ответ 5
У меня также были проблемы с созданием файла PDF из диаграммы рассеяния, созданной с помощью ggplot в ShinyApp. Я добился успеха с подходом, похожим на тот, который использовался в juba, но тогда используемая мной функция nearPoints() не сработала и выдала сообщение об ошибке, сообщающее что-то о невозможности найти координаты. Затем я использовал опцию ggsave, рекомендованную Yihui Xie, но с этой стратегией я получаю файлы, сохраненные в папке, где находится мой ShinyApp. Я беспокоюсь, что если я попытаюсь использовать это в моем ShinyApp, размещенном на сайте shinyapps.io, возникнут проблемы при попытке сохранить эти временные и временные файлы. Я также попытался удалить файл после завершения загрузки, но каждый раз, когда отображается график, файл создается, поэтому файл создается снова после загрузки скопированного файла. Вот пример кода, который я использовал для кнопки загрузки:
filename = function() {
paste('boxPlot_', Sys.Date(), '.pdf', sep='')
},
content = function(file) {
file.copy(paste('boxPlot_', Sys.Date(), '.pdf', sep=''), file, overwrite = TRUE)
# To avoid the accumulation of PDFs in the server
file.remove(paste('boxPlot_', Sys.Date(), '.pdf', sep=''))
}
)
Я предполагаю, что это может вызвать проблемы, если я загружу скрипт ShinyApp в shinyapps.io, который создает один файл PDF каждый раз при визуализации графика, верно?