2013-02-11 5 views
58

Я пытаюсь выяснить, как использовать 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 работает без ошибок, но он не пишет графику.

Любые советы по загрузке сайта, работающие для написания графиков, будут оценены по достоинству.

ответ

35

Не уверен, что этот вопрос по-прежнему активен, но это первый, который появился при поиске «сохранения участков в блестящем приложении», поэтому я хотел бы быстро добавить, как заставить 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  

Обновление

По 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") 
    } 
) 
+0

Я считаю, что ваш ответ на самом деле правильный. Вы также можете просто использовать 'ggsave (файл, plotInput(), device = png)' вместо создания функции устройства (обертки). –

+0

@sebkopf Я пропустил ваш ответ в промежуточный год и немного! – alexwhan

+1

@Yihui Это решение для меня не работает: R версия 3.1.0, ggplot2_1.0.0 shiny_0.10.1. «Сохранить», нажмите «Сохранить», но файл не сохраняется. Может ли кто-нибудь подтвердить? – zx8754

17

Мне не удалось заставить его работать с 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") 
+0

ОК, я соглашусь, что ggsave не будет работать на этом этапе разбирательства с downloadHandler. блестящий 0,3 разваливается с downloadHandler, вы правы. Я опубликую альтернативное решение, которое я выяснил, избегая downloadHandler, который позволит ggsave работать. – alexwhan

+1

@ juba любая идея, почему [эта попытка вывода в pdf] (https://gist.github.com/geotheory/b0c36071b7c0c2b384db) с аналогичным (не ggplot2) методом не работает? Я просто получаю разбитый pdf-файл, который не открывается. Может ли plotInput не доставлять участок вместо объекта plot? – geotheory

20

Вот решение, которое позволяет использовать 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.

Пожалуйста, добавьте предложения, которые могут быть у вас.

+0

Без блока 'isolate' вокруг' input $ filename' любое изменение текстового поля 'filename' также будет запрашивать сохранение файла, если флажок установлен. – jpd527

13

Это старая, но до сих пор топ хит, когда кто-то Googles «R блестящий сохранить 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) 
    } 
) 

Работы для меня.