Parlak bir uygulamada yapılan grafikleri kaydedin


85

Bright ile bir komployu kaydetmek için downloadButton'ı nasıl kullanacağımı anlamaya çalışıyorum. Paketteki örnek, bir .csv dosyasını kaydetmek için downloadButton / downloadHandler'ı gösterir. Buna dayanarak tekrarlanabilir bir örnek yapacağım.

İçin 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')
  )
))

İçin 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())
    }
  )
})

Bu soruyu yanıtlıyorsanız, muhtemelen buna aşinasınızdır, ancak bunu çalıştırmak için yukarıdakileri ayrı komut dosyalarına ( ui.Rve çalışma dizini içindeki server.Rbir klasöre ( foo) kaydedin . Parlak uygulamayı çalıştırmak için, çalıştırın runApp("foo").

Kullanarak ggsave, ggsave'nin filenameişlevi kullanamadığını belirten bir hata mesajı alıyorum (sanırım). Standart grafik cihazını kullanırsam (aşağıdaki gibi) Download Plothatasız çalışır ancak grafiği yazmaz.

DownloadHandler'ın arsa yazmak için çalışması için herhangi bir ipucu takdir edilecektir.

Yanıtlar:


69

Bu sorunun hala aktif olup olmadığından emin değilim, ancak "parlak uygulamada çizimleri kaydetme" aranırken ortaya çıkan ilk soru bu yüzden, ggsave'in downloadHandler ile çalışmasını orijinal sorunun satırlarına hızlı bir şekilde eklemek istedim.

Juba'nın ggsave yerine doğrudan çıktı kullanarak önerdiği alternatif stratejiler ve alexwhan'ın kendisi tarafından önerilen alternatif strateji harika çalışıyor, bu sadece downloadHandler'da ggsave kullanmak isteyenler içindir).

Alexwhan tarafından bildirilen sorun, ggsave'nin dosya uzantısını doğru grafik cihazıyla eşleştirmeye çalışmasından kaynaklanıyor. Bununla birlikte, geçici dosyanın bir uzantısı yoktur, bu nedenle eşleştirme başarısız olur. Bu ggsave, orijinal kod örneğinde olduğu gibi (bir png için) , cihazı işlev çağrısında özel olarak ayarlayarak düzeltilebilir :

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

Bu çağrı temelde alır devicebir işlevini pngo ggsaveiçten atar (siz bakabilirsiniz ggsaveiçin sözdizimi görmek için fonksiyon kodu jpg, pdfvs.). Belki ideal olarak, dosya uzantısı (dosya adından farklıysa - burada geçici dosyada olduğu gibi) bir ggsaveparametre olarak belirtilebilir, ancak bu seçenek şu anda ggsave.


Minimal bir bağımsız çalışma örneği:

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    

Güncelleme

Ggplot2 sürüm 2.0.0'dan itibaren, ggsaveişlev deviceparametre için karakter girişini destekler ; bu, artık downloadHandler tarafından oluşturulan geçici dosyanın, ggsavekullanılacak uzantının örn. "pdf"(Geçmek yerine) bir cihaz işlevinde). Bu, yukarıdaki örneği aşağıdaki gibi basitleştirir

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

1
Cevabınızın burada aslında doğru olduğuna inanıyorum. ggsave(file, plotInput(), device = png)Bir aygıt (sarmalayıcı) işlevi oluşturmak yerine yalnızca kullanabilirsiniz .
Yihui Xie

@sebkopf Aradan geçen yıl içinde cevabınızı kaçırdım ve biraz!
alexwhan

1
@Yihui Bu çözüm benim için çalışmıyor: R sürüm 3.1.0, ggplot2_1.0.0 shiny_0.10.1. Kaydetme kutusu açılır, kaydet seçeneğine tıklayın, ancak hiçbir dosya kaydedilmez. Onaylayan var mı?
zx8754

3
@ zx8754 Cevaba tam bir örnek ekledim. RStudio görüntüleyicide bilinen bir dosya indirememe hatası olduğundan, onu RStudio'da görüntülemek yerine web tarayıcınızda çalıştırmanız gerektiğini unutmayın.
Yihui Xie

1
@sebkopf Evet, gerçek bir örneği denedikten sonra fark ettim, bu yüzden buraya ilk yorumum aslında yanlıştı. Açıklama için teşekkürler!
Yihui Xie

24

İşte parlak grafikleri kaydetmek için ggsave kullanmaya izin veren bir çözüm. Aramak için mantıksal bir onay kutusu ve metin girişi kullanır ggsave(). Bunu ui.Riçindeki dosyaya ekleyin sidebarPanel:

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

Ardından server.R, mevcut output$plotreactivePlot işlevi yerine bunu dosyaya ekleyin :

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

Bir kullanıcı daha sonra metin kutusuna (uzantı olmadan) istenen dosya adını yazabilir ve uygulama dizinine kaydetmek için onay kutusunu işaretleyebilir. Kutunun işaretinin kaldırılması, grafiği yeniden yazdırır. Eminim bunu yapmanın daha düzgün yolları vardır, ancak en azından artık pencerelerde daha güzel png grafikleri için ggsave ve cairo kullanabilirim.

Lütfen sahip olabileceğiniz önerileri ekleyin.


isolateEtrafında bir blok olmadan input$filename, filenamemetin kutusunda yapılacak herhangi bir değişiklik , kutu işaretliyse bir dosya kaydetme isteğinde bulunacaktır.
jpd527

23

Çalışmasını sağlamayı başaramadım ggsave, ancak standart bir çağrı ilepng() sorun yok gibi görünüyor.

Dosyanızın yalnızca bir output$downloadPlotkısmını değiştirdim server.R:

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

Bright'ın 0.3 sürümüyle ilgili bazı sorunlar yaşadığımı unutmayın, ancak en son Github ile çalışıyor:

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

Tamam, ggsave'in downloadHandler ile işlemlerin bu aşamasında çalışmayacağını kabul edeceğim. downloadHandler ile parlak 0.3 parçalanıyor, haklısınız. Ggsave'in çalışmasına izin verecek downloadHandler'dan kaçınmayı anladığım alternatif bir çözüm yayınlayacağım.
alexwhan

1
@juba, bu girişimin neden benzer bir (ggplot2 olmayan) yöntemle pdf'ye çıktı verme girişiminin işe yaramadığına dair bir fikriniz var mı? Sadece açılmayan bozuk bir PDF alıyorum PlotInput, bir çizim nesnesi yerine bir çizim teslim edemez mi?
geotheory

20

Bu eski, ancak yine de birisi Google'da "R parlak tasarruf ggplot" yazdığında en çok vurulan şey, bu yüzden başka bir geçici çözümle katkıda bulunacağım. Çok basit ... grafiğinizi görüntüleyen aynı işlevi ggsave'yi çağırın, bu da grafiği sunucuda bir dosya olarak kaydedecektir.

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

Daha sonra downloadHandler'ı kullanın file.copy()ve mevcut dosyadaki verileri "file" parametresine yazmak için kullanın .

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

Benim için çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.