Lưu các âm mưu được thực hiện trong một ứng dụng sáng bóng


85

Tôi đang cố gắng tìm ra cách sử dụng downloadButton để lưu một cốt truyện bằng sáng bóng. Ví dụ trong gói minh họa downloadButton / downloadHandler để lưu .csv. Tôi sẽ làm một ví dụ có thể tái tạo dựa trên đó.

Đối với 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')
  )
))

Đối với 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())
    }
  )
})

Nếu bạn đang trả lời câu hỏi này, có thể bạn đã quen thuộc với điều này, nhưng để điều này hoạt động, hãy lưu ở trên vào các tập lệnh riêng biệt ( ui.Rserver.Rvào một thư mục ( foo) trong thư mục làm việc. Để chạy ứng dụng sáng bóng, hãy chạy runApp("foo").

Khi sử dụng ggsave, tôi nhận được thông báo lỗi cho biết rằng ggsave không thể sử dụng filenamechức năng (tôi nghĩ vậy). Nếu tôi sử dụng thiết bị đồ họa tiêu chuẩn (như bên dưới), các Download Plottác phẩm hoạt động không có lỗi, nhưng nó không ghi hình ảnh.

Bất kỳ mẹo nào để tải xuống Trình xử lý làm việc để viết các âm mưu sẽ được đánh giá cao.

Câu trả lời:


69

Không chắc liệu câu hỏi này có còn hoạt động hay không nhưng đây là câu hỏi đầu tiên xuất hiện khi tìm kiếm "lưu các mảnh đất trong ứng dụng sáng bóng", vì vậy tôi muốn nhanh chóng thêm cách để ggsave hoạt động với downloadHandler theo dòng của câu hỏi ban đầu.

Các chiến lược thay thế do juba đề xuất bằng cách sử dụng đầu ra trực tiếp thay vì ggsave và chiến lược thay thế do chính alexwhan đề xuất đều hoạt động tốt, điều này chỉ dành cho những người hoàn toàn muốn sử dụng ggsave trong downloadHandler).

Sự cố do alexwhan báo cáo là do ggsave đang cố gắng khớp phần mở rộng tệp với đúng thiết bị đồ họa. Tuy nhiên, tệp tạm thời không có phần mở rộng nên quá trình khớp không thành công. Điều này có thể được khắc phục bằng cách thiết lập cụ thể thiết bị trong lệnh ggsavegọi hàm, giống như trong ví dụ mã gốc (đối với 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)
    }
)

Cuộc gọi này về cơ bản có các devicechức năng cho một pngggsavechuyển nhượng nội bộ (bạn có thể nhìn vào các ggsavemã chức năng để xem cú pháp cho jpg, pdf, vv). Có lẽ, lý tưởng nhất là người ta có thể chỉ định phần mở rộng tệp (nếu khác với tên tệp - như trường hợp ở đây đối với tệp tạm thời) làm ggsavetham số nhưng tùy chọn này hiện không khả dụng ggsave.


Một ví dụ làm việc khép kín tối thiểu:

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    

Cập nhật

Kể từ phiên bản ggplot2 2.0.0, ggsavehàm hỗ trợ nhập ký tự cho devicetham số, điều đó có nghĩa là tệp tạm thời được tạo bởi downloadHandler hiện có thể được lưu bằng lệnh gọi trực tiếp đến ggsavebằng cách chỉ định rằng phần mở rộng được sử dụng phải là ví dụ "pdf"(thay vì truyền trong một chức năng của thiết bị). Điều này đơn giản hóa ví dụ trên thành sau

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

1
Tôi tin rằng câu trả lời của bạn thực sự là một trong những chính xác ở đây. Bạn cũng có thể chỉ sử dụng ggsave(file, plotInput(), device = png)thay vì tạo một hàm thiết bị (trình bao bọc).
Yihui Xie

@sebkopf Tôi đã bỏ lỡ câu trả lời của bạn vào giữa năm và một chút!
alexwhan

1
@Yihui Giải pháp này không phù hợp với tôi: R phiên bản 3.1.0, ggplot2_1.0.0 gloss_0.10.1. Hộp lưu bật lên, nhấp vào lưu, nhưng không có tệp nào được lưu. Bất cứ ai có thể xác nhận?
zx8754

3
@ zx8754 Tôi chỉ thêm một ví dụ đầy đủ cho câu trả lời. Lưu ý rằng bạn nên chạy nó trong trình duyệt web của bạn thay vì xem nó trong RStudio, vì trình xem RStudio có một lỗi đã biết là không thể tải xuống tệp.
Yihui Xie

1
@sebkopf Có, tôi nhận ra điều đó sau khi thử một ví dụ thực tế, vì vậy nhận xét đầu tiên của tôi ở đây thực sự sai. Cảm ơn bạn đã làm rõ!
Yihui Xie

24

Đây là một giải pháp cho phép sử dụng ggsave để lưu các ô sáng bóng. Nó sử dụng hộp kiểm logic và đầu vào văn bản để gọi ggsave(). Thêm cái này vào ui.Rtệp bên trong sidebarPanel:

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

Sau đó thêm nó vào server.Rtệp thay vì output$plothàm ReativePlot hiện tại :

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

Sau đó, người dùng có thể nhập tên tệp mong muốn vào hộp văn bản (không có phần mở rộng) và đánh dấu vào hộp kiểm để lưu trong thư mục ứng dụng. Bỏ chọn hộp sẽ in lại cốt truyện. Tôi chắc rằng có nhiều cách gọn gàng hơn để làm điều này, nhưng ít nhất bây giờ tôi có thể sử dụng ggsave và cairo trong windows để có đồ họa png đẹp hơn nhiều.

Vui lòng thêm bất kỳ đề xuất nào bạn có thể có.


Không có isolatekhối xung quanh input$filename, bất kỳ thay đổi nào đối với filenamehộp văn bản cũng sẽ nhắc lưu tệp nếu hộp được chọn.
jpd527

23

Tôi đã không quản lý để làm cho nó hoạt động ggsave, nhưng với một cuộc gọi tiêu chuẩn đếnpng() nó có vẻ ổn.

Tôi chỉ thay đổi output$downloadPlotmột phần server.Rtệp của bạn :

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

Lưu ý rằng tôi đã gặp một số vấn đề với phiên bản sáng bóng 0.3, nhưng nó hoạt động với phiên bản mới nhất từ ​​Github:

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

Được rồi, tôi chấp nhận rằng ggsave sẽ không hoạt động ở giai đoạn thủ tục này với downloadHandler. sáng bóng 0,3 tan rã với downloadHandler, bạn đã đúng. Tôi sẽ đăng một giải pháp thay thế mà tôi đã tìm ra để tránh downloadHandler sẽ cho phép ggsave hoạt động.
alexwhan

1
@juba có bất kỳ ý kiến ​​nào tại sao nỗ lực xuất thành pdf với phương thức tương tự (không phải ggplot2) này không hoạt động không? Tôi chỉ nhận được một bản pdf bị hỏng không mở được. PlotInput không thể phân phối một âm mưu thay vì một đối tượng âm mưu?
geotheory

20

Tính năng này đã cũ, nhưng vẫn là thành công hàng đầu khi ai đó sử dụng "R sáng bóng save ggplot", vì vậy tôi sẽ đóng góp một giải pháp khác. Rất đơn giản ... hãy gọi ggsave trong cùng một hàm hiển thị biểu đồ của bạn, hàm này sẽ lưu biểu đồ dưới dạng tệp trên máy chủ.

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

Sau đó, sử dụng downloadHandler và sử dụng file.copy()để ghi dữ liệu từ tệp hiện có vào tham số "tệp".

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

Làm việc cho tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.