2013-02-11 23 views
58

Tôi đang cố gắng tìm hiểu cách sử dụng nút DownloadButton để lưu một ô có bóng. Ví dụ trong gói thể hiện downloadButton/downloadHandler để lưu tệp .csv. Tôi sẽ làm một ví dụ tái sản xuất dựa trên đó.Lưu các ô được tạo trong một ứng dụng sáng bóng

Đố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 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, bạn có thể quen với điều này, nhưng để làm việc này, hãy lưu ở trên vào kịch bản riêng biệt (ui.Rserver.R vào thư mục (foo) trong thư mục hoạt động. Để chạy ứng dụng sáng bóng, hãy chạy runApp("foo").

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 chức năng filename (tôi nghĩ). Nếu tôi sử dụng thiết bị đồ họa tiêu chuẩn (như dưới đây), các Download Plot hoạt động mà không có một lỗi, nhưng nó không viết đồ họa.

Bất kỳ mẹo nào để tải xuốngHandler làm việc để viết lô sẽ được đánh giá cao.

Trả lời

35

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

Các chiến lược thay thế được đề xuất bởi juba sử dụng đầu ra trực tiếp thay vì ggsave và chiến lược thay thế được đề xuất bởi chính bản thân cả hai làm việc tuyệt vời, đ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ố được báo cáo bởi alexwhan là do ggsave cố gắng khớp phần mở rộng tệp với thiết bị đồ họa chính xác. Tuy nhiên, tệp tạm thời không có phần mở rộng để kết hợp không thành công. Điều này có thể được khắc phục bằng cách đặc biệt thiết lập các thiết bị trong các cuộc gọi ggsave chức năng, như vậy trong ví dụ mã gốc (đối với một 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 device chức năng cho một png rằng ggsave gán nội bộ (bạn có thể xem mã chức năng ggsave để xem cú pháp cho jpg, pdf, v.v ...). Có lẽ, lý tưởng nhất, người ta có thể chỉ định phần mở rộng của tệp (nếu khác với tên tệp - như trường hợp ở đây cho tệp tạm thời) dưới dạng tham số ggsave nhưng tùy chọn này hiện không có sẵn trong ggsave.


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

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

Tính đến ggplot2 phiên bản 2.0.0, các ggsave chức năng hỗ trợ nhân vật đầu vào cho tham số device, có nghĩa là tạm thời tập tin được tạo bởi downloadHandler bây giờ có thể được lưu với một cuộc gọi trực tiếp đến ggsave bằng cách xác định rằng phần mở rộng được sử dụng nên ví dụ "pdf" (thay vì truyền chức năng thiết bị). Này đơn giản hóa ví dụ trên như sau

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

Tôi tin câu trả lời của bạn thực sự là câu trả lời đúng ở đây. Bạn cũng có thể sử dụng 'ggsave (file, plotInput(), device = png)' thay vì tạo một hàm (wrapper) của thiết bị. –

+0

@sebkopf Tôi đã bỏ lỡ câu trả lời của bạn trong năm can thiệp và một chút! – alexwhan

+1

@Yihui Giải pháp này không hoạt động đối với tôi: Phiên bản R 3.1.0, ggplot2_1.0.0 shiny_0.10.1. Lưu hộp bật lên, nhấp vào lưu, nhưng không có tệp nào được lưu. Có ai xác nhận không? – zx8754

17

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

tôi chỉ thay đổi output$downloadPlot phần của server.R tập tin 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 đã có một số vấn đề với phiên bản 0.3 của sáng bóng, nhưng nó làm việc với các mới nhất từ ​​Github:

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

OK, tôi sẽ chấp nhận rằng ggsave sẽ không hoạt động ở giai đoạn này của thủ tục với downloadHandler. sáng bóng 0.3 rơi ngoài với downloadHandler, bạn nói đúng. Tôi sẽ đăng một giải pháp thay thế, tôi đã tìm ra cách tránh downloadHandler cho phép ggsave hoạt động. – alexwhan

+1

@juba bất kỳ ý tưởng nào tại sao [nỗ lực này để xuất ra pdf] (https://gist.github.com/geotheory/b0c36071b7c0c2b384db) với phương thức (non-ggplot2) tương tự không hoạt động? Tôi chỉ nhận được một pdf bị hỏng mà không mở. Có thể plotInput không cung cấp một cốt truyện thay vì một đối tượng cốt truyện? – geotheory

20

Đây là 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 hợp lý và kiểu nhập văn bản để gọi ggsave(). Thêm phần này vào file ui.R bên sidebarPanel:

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

Sau đó thêm video này vào file server.R thay vì chức năng output$plot reactivePlot 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()) 
    }) 

Người dùng có thể sau đó gõ tên tập tin mong muốn trong hộp văn bản (mà 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 ô. Tôi chắc chắn có nhiều cách để làm điều này, nhưng ít nhất tôi bây giờ có thể sử dụng ggsave và cairo trong cửa sổ cho đồ 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ó.

+0

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

13

Đây là cũ, nhưng vẫn là hit đầu khi ai đó Googles "R sáng bóng lưu ggplot", vì vậy tôi sẽ góp phần workaround khác. Rất đơn giản ... gọi ggsave trong cùng một chức năng hiển thị biểu đồ của bạn, 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ử downloadHandler và sử dụng file.copy() để ghi dữ liệu từ tập tin hiện có để tham số "File".

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

Làm việc cho tôi.

Các vấn đề liên quan