2013-02-11 5 views
58

Próbuję dowiedzieć się, jak użyć funkcji downloadButton, aby zapisać fabułę za pomocą błyszczącej. Przykład w pakiecie demonstruje downloadButton/downloadHandler, aby zapisać plik .csv. W oparciu o to zrobię powtarzalny przykład.Zapisywanie działek w błyszczącej aplikacji

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

Dla 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()) 
    } 
) 
}) 

Jeśli odpowiedzi na to pytanie, prawdopodobnie jesteś zaznajomiony z tym, ale aby dostać tę pracę, zapisać powyższe pod oddzielne skrypty (ui.R ido folderu (foo) w katalogu roboczym. Aby uruchomić błyszczącą aplikację, uruchom runApp("foo").

Przy użyciu ggsave, pojawia się komunikat o błędzie informujący, że ggsave nie może użyć funkcji filename (myślę). Jeśli używam standardowego urządzenia graficznego (jak poniżej), Download Plot działa bezbłędnie, ale nie zapisuje grafiki.

Wszelkie wskazówki, jak pobrać dział pomocy w pisaniu działek, będą mile widziane.

Odpowiedz

35

Nie jestem pewien, czy to pytanie jest nadal aktywne, ale jest pierwszym, które pojawiło się podczas wyszukiwania "oszczędzania działek w błyszczącej aplikacji", więc chciałem szybko dodać, jak uzyskać ggsave do pracy z downloadHandler zgodnie z oryginałem pytanie.

Alternatywne strategie sugerowane przez jubę, wykorzystujące bezpośrednie wyjście zamiast ggsave i alternatywną strategię sugerowaną przez samego alexwhana, działają świetnie, to jest właśnie dla tych, którzy absolutnie chcą użyć ggsave w downloadHandler).

Problem zgłoszony przez alexwhan jest spowodowany przez ggsave, który próbuje dopasować rozszerzenie pliku do właściwego urządzenia graficznego. Plik tymczasowy nie ma jednak rozszerzenia, więc dopasowanie nie powiedzie się. Można temu zaradzić przez specyficzne ustawienie urządzenia w wywołaniu ggsave funkcyjnej, tak jak w oryginalnym przykład kod (na 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) 
    } 
) 

toll zasadniczo wykonuje funkcję device dla png że ggsave przypisuje wewnętrznie (możesz przejrzeć kod funkcji ggsave, aby zobaczyć składnię dla jpg, pdf itd.). Być może najlepiej byłoby określić rozszerzenie pliku (jeśli różni się ono od nazwy pliku - tak jak w przypadku pliku tymczasowego) jako parametr ggsave, ale ta opcja nie jest obecnie dostępna w ggsave.


Minimalny samowystarczalny przykład praca:

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  

Aktualizacja

Począwszy od wersji 2.0.0 ggplot2, funkcja ggsave obsługuje znaków wejście dla parametru device, co oznacza, że ​​tymczasowa plik utworzony przez funkcję pobieraniaHandler można teraz zapisać za pomocą bezpośredniego połączenia z numerem ggsave, określając, że rozszerzeniem, które ma być używane, powinno być np. "pdf" (zamiast przekazywania funkcji urządzenia). Upraszcza to powyższy przykład z następującym

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

Wierzę, że twoja odpowiedź jest rzeczywiście właściwa tutaj. Możesz także użyć 'ggsave (file, plotInput(), device = png)' zamiast tworzyć funkcję urządzenia (wrapper). –

+0

@sebkopf Tęskniłem za twoją odpowiedzią w przeciągu roku i trochę! – alexwhan

+1

@Yihui To rozwiązanie nie działa dla mnie: R wersja 3.1.0, ggplot2_1.0.0 shiny_0.10.1. Zostanie wyświetlone okno Zapisz, kliknij przycisk Zapisz, ale plik nie zostanie zapisany. Czy ktoś może potwierdzić? – zx8754

17

Nie udało mi się sprawić, aby działało z ggsave, ale ze standardowym połączeniem z png() wydaje się być w porządku.

ja tylko zmienił output$downloadPlot część pliku server.R:

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

Zauważ, że miałem pewne problemy z wersją błyszczące 0.3, ale działa z najnowszym z Github:

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

OK, zamierzam przyjąć, że ggsave nie będzie działać na tym etapie postępowania z downloadHandler. błyszczący 0.3 rozpada się wraz z downloadHandler, masz rację. Postawię alternatywne rozwiązanie, które wymyśliłem, unikając downloadHandler, który pozwoli ggsave działać. – alexwhan

+1

@juba każdy pomysł, dlaczego [ta próba wyjścia do pdf] (https://gist.github.com/geotheory/b0c36071b7c0c2b384db) z podobną (non-ggplot2) metoda nie działa? Właśnie mam uszkodzony plik pdf, który się nie otwiera. Czy funkcja plotInput może nie wyświetlać wykresu zamiast obiektu wydruku? – geotheory

20

Oto rozwiązanie, które pozwala na używanie ggsave do zapisywania błyszczących wątków. Używa logicznego pola wyboru i wprowadzania tekstu, aby zadzwonić pod numer ggsave(). Dodaj do tego pliku ui.R wewnątrz sidebarPanel:

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

Następnie dodać do tego pliku server.R zamiast bieżącej funkcji output$plot reactivePlot:

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

Użytkownik może następnie wpisz żądaną nazwę pliku w polu tekstowym (bez rozszerzenia) i zaznacz to pole wyboru, aby zapisać w katalogu aplikacji. Odznaczenie pola powoduje ponowne wydrukowanie wykresu. Jestem pewien, że są na to sposoby, ale przynajmniej mogę teraz użyć ggsave i cairo w oknach, by uzyskać ładniejszą grafikę png.

Proszę dodać wszelkie sugestie.

+0

Bez bloku 'izoluj' wokół' input $ filename', każda zmiana w polu tekstowym 'filename' spowoduje również monit o zapisanie pliku, jeśli pole jest zaznaczone. – jpd527

13

To jest stary, ale nadal top hit kiedy ktoś google „R błyszczące zapisać ggplot”, więc będę przyczynić innego obejścia. Bardzo proste ... wywołaj ggsave w tej samej funkcji, która wyświetla twój wykres, który zapisze wykres jako plik na serwerze.

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

Następnie użyj downloadHandler i używać file.copy() do zapisu danych z istniejącego pliku do parametru „Plik”.

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

Działa u mnie.