使用 Shiny downloadHandler 将多个数据帧保存到单个 csv 文件

Saving multiple data-frames to single csv file using Shiny downloadHandler

我有一个 RShiny 应用程序,我在其中跨不同的选项卡设置面板显示多个数据框。我希望能够将出现在每个面板上的数据帧写入每个面板的一个 csv 文件。我目前正在尝试使用 Shiny 的 downloadHandler 选项来渲染它。

做了一点研究,发现我可以使用 sink() 函数将 R 输出转移到一个文件。

这是我尝试将 sink() 合并到 server.R 侧的一个这样的按钮中的尝试

output$downloadDemographic <- downloadHandler(
filename = function() {
  paste('Demographics', '.csv', sep='')
},
content = function(file) {
  sink("Demographics.csv")
  cat('Population Demographics')
  write.csv(Population)
  cat('Geography Demographics')
  write.csv(Geography)
  sink()
}
) 

其中 PopulationGeography 是两个具有相同列数但名称不同的数据框。

接收器功能自动将上述数据帧写入 csv 文件 'Demographics.csv' 到我的工作目录,但 Shiny 上的 downloadHandler 选项提示用户即时保存 csv 文件。有点与我在这里想要实现的目标相矛盾。我可能遗漏了什么或犯了一个明显的错误,我不知道。

期望的输出 - https://i.stack.imgur.com/yddrE.jpg

I could render multiple download buttons, write each of the data-frames to multiple csv files but some of my tab setted elements have as many as 8 data-frames and this would make the UI messy.

I could coerce multiple data-frames into a single one before writing to a csv file but they are all unequal sized dataframes and formatting them into the desired output would be a huge pain.

关于我如何以任何其他方式建立它的任何想法?

谢谢!

其他选项:

  1. 写一个 Excel 工作簿,每个 sheet 数据框
  2. 将多个 csv 压缩在一起 文件

这是使用 R 数据集包中的四个数据帧的两个选项的示例。

library(shiny)
library(xlsx)

shinyApp(
    ui = fluidPage(
        downloadButton("downloadExcelSheet", "Download Excel Workbook with Multiple Sheets"),
        downloadButton("downloadZippedCSV", "Download zipped csv files")
    ),
    server = function(input, output) { 

        #### Write an Excel workbook with one sheet per dataframe ####
        output$downloadExcelSheet <- downloadHandler(
            filename = function() {
                "excelWorkbook.xlsx"
            },
            content = function(file) {
                # write workbook and first sheet
                write.xlsx(mtcars, file, sheetName = "mtcars", append = FALSE)

                # add other sheets for each dataframe
                listOtherFiles <- list(iris = iris, 
                                       airquality = airquality, 
                                       sleep = sleep)
                for(i in 1:length(listOtherFiles)) {
                    write.xlsx(listOtherFiles[i], file, 
                               sheetName = names(listOtherFiles)[i], append = TRUE)
                }
            }
        )

        #### Zip together multiple csv files ####
        output$downloadZippedCSV <- downloadHandler(
            filename = function() {
                "zippedCSV.zip"
            },
            content = function(file) {
                # go to temp dir to avoid permission issues
                owd <- setwd(tempdir())
                on.exit(setwd(owd))

                # create list of dataframes and NULL value to store fileNames
                listDataFrames <- list(mtcars = mtcars, 
                                       iris = iris,
                                       airquality = airquality,
                                       sleep = sleep)
                allFileNames <- NULL

                # loop through each dataframe
                for(i in 1:length(listDataFrames)) {
                    # write each dataframe as csv and save fileName
                    fileName <- paste0(names(listDataFrames)[i], ".csv")
                    write.csv(listDataFrames[1], fileName)
                    allFileNames <- c(fileName, allFileNames)
                }

                # write the zip file
                zip(file, allFileNames) 

            }
        )
    }
)