将多个 data.frame 导出到多个 Excel 工作表的简单方法

Easy way to export multiple data.frame to multiple Excel worksheets

提问人:Ogre Magi 提问时间:12/31/2014 最后编辑:zx8754Ogre Magi 更新时间:6/9/2021 访问量:287374

问:

我惊讶地发现没有简单的方法可以将多个 data.frame 导出到 Excel 文件的多个工作表?我尝试了 xlsx 包,似乎它只能写入一张纸(覆盖旧纸);我也尝试过 WriteXLS 包,但它一直给我错误......

我的代码结构是这样的:根据设计,对于每次迭代,输出数据帧 (tempTable) 和 sheetName (sn) 都会更新并导出到一个选项卡中。

for (i in 2 : ncol(code)){ 
        ...
        tempTable <- ...
        sn <- ...
        WriteXLS("tempTable", ExcelFileName = "C:/R_code/../file.xlsx",
              SheetNames = sn);
}

我可以导出到多个 cvs 文件,但必须有一种简单的方法可以在 Excel 中做到这一点,对吧?

r excel xlsx

评论

3赞 joran 12/31/2014
你对 xlsx 的看法错了。有一个功能,它允许您创建新工作表,然后在循环中写入它们。此外,XLConnect 中的等效函数是矢量化的,允许将数据帧列表写入多个工作表。createSheet
0赞 Ogre Magi 12/31/2014
@joran,createSheet 与 addDataFrame 一起使用,而不是 write.xlsx?我之前在文档中看到了这一点,但无法弄清楚整个过程。

答:

8赞 nrussell 12/31/2014 #1

我不熟悉这个包;我一般使用:WriteXLSXLConnect

library(XLConnect)
##
newWB <- loadWorkbook(
  filename="F:/TempDir/tempwb.xlsx",
  create=TRUE)
##
for(i in 1:10){
  wsName <- paste0("newsheet",i)
  createSheet(
    newWB,
    name=wsName)
  ##
  writeWorksheet(
    newWB,
    data=data.frame(
      X=1:10,
      Dataframe=paste0("DF ",i)),
    sheet=wsName,
    header=TRUE,
    rownames=NULL)
}
saveWorkbook(newWB)

如上所述,这当然可以矢量化@joran,但为了快速生成动态工作表名称,我使用了一个循环来演示。for

我在创建新的 .xlsx 文件时使用了该参数,但是如果您的文件已经存在,则不必指定此参数,因为默认值为 .create=TRUEloadWorkbookFALSE

以下是已创建工作簿的一些屏幕截图:

enter image description here

enter image description here

enter image description here

评论

1赞 Ogre Magi 12/31/2014
我没有使用XLConnect,非常详细的例子,谢谢!
0赞 nrussell 12/31/2014
不客气 - 我发现这是一个非常有用的软件包。CRAN 上有一个非常好的小插曲,详细介绍了一些主要功能,第 4 节中有一个很好的例子,演示了如何将 R 图写入工作表。
191赞 eipi10 12/31/2014 #2

您可以使用包写入多个工作表。您只需要为每个数据框使用不同的数据框,并且需要添加:xlsxsheetNameappend=TRUE

library(xlsx)
write.xlsx(dataframe1, file="filename.xlsx", sheetName="sheet1", row.names=FALSE)
write.xlsx(dataframe2, file="filename.xlsx", sheetName="sheet2", append=TRUE, row.names=FALSE)

另一个选项是,在 R/xlsx 代码中执行所有操作,然后在最后保存工作簿,以便更好地控制格式设置和数据框的放置位置。例如:

wb = createWorkbook()

sheet = createSheet(wb, "Sheet 1")

addDataFrame(dataframe1, sheet=sheet, startColumn=1, row.names=FALSE)
addDataFrame(dataframe2, sheet=sheet, startColumn=10, row.names=FALSE)

sheet = createSheet(wb, "Sheet 2")

addDataFrame(dataframe3, sheet=sheet, startColumn=1, row.names=FALSE)

saveWorkbook(wb, "My_File.xlsx")

如果您觉得它有用,这里有一些有趣的辅助函数,可以更轻松地使用以下命令向电子表格添加格式、元数据和其他功能: http://www.sthda.com/english/wiki/r2excel-read-write-and-format-easily-excel-files-using-r-softwarexlsx

评论

2赞 eipi10 8/15/2016
“添加”以删除行名。row.names=FALSE
4赞 eipi10 6/13/2018
@EcologyTom,我前段时间从切换到,因为我发现它更直观,并且还避免了对 java 的依赖。xlsxopenxlsx
10赞 NewBee 8/22/2020
是只有我,还是当使用此代码时,工作表 2 只是写在工作表 1 上?
1赞 Macosso 9/7/2021
似乎这个解决方案不起作用,工作表 2 写在工作表 1 上
1赞 Catalyst 1/20/2023
此解决方案似乎适用于某些人,但不适用于其他人。至于我,它还覆盖了 sheet1 而不是生成单独的工作表。EcologyTom 和 Syed 给出的解决方案对我有用。
164赞 Syed 4/6/2016 #3

您还可以使用 openxlsx 库将多个数据集导出到单个工作簿中的多个工作表。openxlsx 相对于 xlsx 的优势在于 openxlsx 消除了对 java 库的依赖。

使用列表名称作为工作表名称将 data.frames 列表写入各个工作表。

require(openxlsx)
list_of_datasets <- list("Name of DataSheet1" = dataframe1, "Name of Datasheet2" = dataframe2)
write.xlsx(list_of_datasets, file = "writeXLSX2.xlsx")

评论

3赞 Hanjo Odendaal 4/6/2016
我已经使用了这些包,我认为它是最快的 c++。 会吃掉你的RAM。您可能希望在 和 之间进行一些基准测试openxlsxXlConnectxlsxopenxlsx
2赞 buhtz 8/15/2016
该包装的另一个优点是它处理了第一行的 R 编号。
8赞 Djork 3/30/2017
谢谢,这是要走的路......我保存了 11 张纸,每张纸都是 20,000x10 的数据帧,在附加第二张纸后出错需要几秒钟openxlsx::write.xlsxxlsx::write.xlsxjava.lang.OutOfMemoryError: Java heap space
0赞 mondano 5/19/2017
我需要添加参数来写入 .xlsx,使其一次将多个工作表写入一个 Excel 文件append=TRUE
0赞 Lionel Trebuchon 6/25/2019
可爱!我创建了我的列表作为循环的一部分,只需要初始化它(),然后使用temp_key和在循环期间构造的temp_df填充它()。尽管我需要创建 16 张纸,但它的写作速度也非常快!有没有人在创作过程中目睹过记忆问题?list_of_dfs <- list()list_of_dfs[[temp_key]] = temp_df
0赞 setempler 5/11/2016 #4

对我来说,提供了您正在寻找的功能。由于您没有指定它返回哪些错误,因此我向您展示一个示例:WriteXLS

library(WriteXLS)
x <- list(sheet_a = data.frame(a=letters), sheet_b = data.frame(b = LETTERS))
WriteXLS(x, "test.xlsx", names(x))

解释

如果是:x

  • 数据帧列表,每个数据帧都写入单个工作表
  • 一个字符向量(R 对象),每个对象都写入单个工作表
  • 别的东西,然后另见帮助说明的内容:

有关使用的更多信息

?WriteXLS

显示:

`x`: A character vector or factor containing the names of one or
     more R data frames; A character vector or factor containing
     the name of a single list which contains one or more R data
     frames; a single list object of one or more data frames; a
     single data frame object.

溶液

对于您的示例,您需要在循环期间收集列表中的所有 data.frames,并在循环完成后使用。WriteXLS

会议信息

  • 建议 3.2.4
  • 写入XLS 4.0.0

评论

0赞 R Yoda 1/28/2018
这个包可以工作,但恕我直言,我会尽量避免对 perl 的依赖(就像我会尽量避免对 Java 的依赖一样),因为它使设置变得更加困难xlsx
5赞 ayush varshney 3/30/2017 #5

如果数据量很小,R 有许多包和函数,可以根据您的要求使用。

write.xlsx、write.xlsx2、XLconnect 也可以完成这项工作,但与 openxlsx 相比,这些有时很慢

因此,如果您正在处理大型数据集并遇到 java 错误。我建议看看“openxlsx”,这真的很棒,并将时间减少到 1/12。

我已经测试了所有功能,最后我对 openxlsx 功能的性能印象深刻。

以下是将多个数据集写入多个工作表的步骤。

 install.packages("openxlsx")
 library("openxlsx")

    start.time <- Sys.time()

    # Creating large data frame
    x <- as.data.frame(matrix(1:4000000,200000,20))
    y <- as.data.frame(matrix(1:4000000,200000,20))
    z <- as.data.frame(matrix(1:4000000,200000,20))

    # Creating a workbook
    wb <- createWorkbook("Example.xlsx")
    Sys.setenv("R_ZIPCMD" = "C:/Rtools/bin/zip.exe") ## path to zip.exe

Sys.setenv(“R_ZIPCMD” = “C:/Rtools/bin/zip.exe”) 必须是静态的,因为它引用了 Rtools 中的一些实用程序。

注意:如果您的系统上未安装 Rtools,请先安装以获得流畅的体验。以下是供您参考的链接:(选择适当的版本)

https://cran.r-project.org/bin/windows/Rtools/ 根据下面的链接检查选项(安装时需要选中所有复选框)

https://cloud.githubusercontent.com/assets/7400673/12230758/99fb2202-b8a6-11e5-82e6-836159440831.png

    # Adding a worksheets : parameters for addWorksheet are 1. Workbook Name 2. Sheet Name

    addWorksheet(wb, "Sheet 1")
    addWorksheet(wb, "Sheet 2")
    addWorksheet(wb, "Sheet 3")

    # Writing data in to respetive sheets: parameters for writeData are 1. Workbook Name 2. Sheet index/ sheet name 3. dataframe name

    writeData(wb, 1, x)

    # incase you would like to write sheet with filter available for ease of access you can pass the parameter withFilter = TRUE in writeData function.
    writeData(wb, 2, x = y, withFilter = TRUE)

    ## Similarly writeDataTable is another way for representing your data with table formatting:

    writeDataTable(wb, 3, z)

    saveWorkbook(wb, file = "Example.xlsx", overwrite = TRUE)

    end.time <- Sys.time()
    time.taken <- end.time - start.time
    time.taken

OpenXLSX 包非常适合从 Excel 文件中读取和写入大量数据,并且有很多用于在 Excel 中自定义格式的选项。

有趣的事实是,我们在这里不必为java堆内存而烦恼。

59赞 Giora Simchoni 11/1/2017 #6

镇上有一个来自 rOpenSci 的新库:writexl

基于 xlsx 导出器的便携式轻量级数据帧 libxlsxwriter 中。无需 Java 或 Excel

我发现它比上述建议更好更快(使用开发版本):

library(writexl)
sheets <- list("sheet1Name" = sheet1, "sheet2Name" = sheet2) #assume sheet1 and sheet2 are data frames
write_xlsx(sheets, "path/to/location")

评论

1赞 Ape 11/9/2017
谢谢!这在 openxlsx 没有的地方起作用(我无法在工作中安装 rtools)。
0赞 JAD 11/9/2017
你使用哪个版本?默认的 cran 下载不支持多个工作表(尚):' writexl::write_xlsx(list(... : 参数 x 必须是数据帧或数据帧列表 '
0赞 Giora Simchoni 11/9/2017
正如我所写的,开发版本。
0赞 Ape 11/10/2017
@JarkoDubbeldam:我从cran安装了我的,多张纸对我有用(R 3.3.0)。检查列表中的对象是否为 data.frames。
0赞 Cina 5/12/2020
这是一个真正有效的。无法在 R 中安装 XLSX。
0赞 makarand kulkarni 2/18/2018 #7

我使用以下函数以这种方式为 openxlsx 执行此操作

mywritexlsx<-function(fname="temp.xlsx",sheetname="Sheet1",data,
                  startCol = 1, startRow = 1, colNames = TRUE, rowNames = FALSE)
{
  if(! file.exists(fname))
    wb = createWorkbook()
  else
   wb <- loadWorkbook(file =fname)
  sheet = addWorksheet(wb, sheetname)

  writeData(wb,sheet,data,startCol = startCol, startRow = startRow, 
          colNames = colNames, rowNames = rowNames)
  saveWorkbook(wb, fname,overwrite = TRUE)
}

评论

0赞 makarand kulkarni 7/17/2018
loadWorkbook 是打开现有文件的关键
0赞 makarand kulkarni 7/18/2018
此外,如果想将公式写入 excel,则有名为 writeFormula 的不同函数,此外,一旦您编写公式,文件需要刷新或重新打开,然后保存,然后在 excel 中关闭。演示在这里给出 [链接(stackoverflow.com/questions/46914303/...)
35赞 EcologyTom 6/13/2018 #8

这里有很多很好的答案,但其中一些有点过时了。如果您想将更多工作表添加到单个文件,那么这是我发现适合我的方法。为清楚起见,以下是版本 4.0 的工作流openxlsx

# Create a blank workbook
OUT <- createWorkbook()

# Add some sheets to the workbook
addWorksheet(OUT, "Sheet 1 Name")
addWorksheet(OUT, "Sheet 2 Name")

# Write the data to the sheets
writeData(OUT, sheet = "Sheet 1 Name", x = dataframe1)
writeData(OUT, sheet = "Sheet 2 Name", x = dataframe2)

# Export the file
saveWorkbook(OUT, "My output file.xlsx")

编辑

我现在已经尝试了其他一些答案,我真的很喜欢@Syed的答案。它没有利用所有功能,但如果您想要一种快速简便的导出方法,那么这可能是最直接的。openxlsx

0赞 Suman C 4/30/2019 #9

我一直在这样做,我所做的只是

WriteXLS::WriteXLS(
    all.dataframes,
    ExcelFileName = xl.filename,
    AdjWidth = T,
    AutoFilter = T,
    FreezeRow = 1,
    FreezeCol = 2,
    BoldHeaderRow = T,
    verbose = F,
    na = '0'
  )

所有这些数据帧都来自这里

all.dataframes <- vector()
for (obj.iter in all.objects) {
  obj.name <- obj.iter
  obj.iter <- get(obj.iter)
  if (class(obj.iter) == 'data.frame') {
      all.dataframes <- c(all.dataframes, obj.name)
}

显然,sapply 例程在这里会更好

0赞 MinimaMoralia 5/14/2019 #10

对于 lapply 友好的版本..

library(data.table)
library(xlsx)

path2txtlist <- your.list.of.txt.files
wb <- createWorkbook()
lapply(seq_along(path2txtlist), function (j) {
sheet <- createSheet(wb, paste("sheetname", j))
addDataFrame(fread(path2txtlist[j]), sheet=sheet, startColumn=1, row.names=FALSE)
})

saveWorkbook(wb, "My_File.xlsx")

评论

1赞 tshimkus 5/14/2019
您能否为这个答案添加一些描述,以提供如何回答问题的上下文?
4赞 alexmathios 7/18/2019 #11

我遇到了这个确切的问题,我是这样解决的:

library(openxlsx) # loads library and doesn't require Java installed

your_df_list <- c("df1", "df2", ..., "dfn")

for(name in your_df_list){
  write.xlsx(x = get(name), 
             file = "your_spreadsheet_name.xlsx", 
             sheetName = name)
}

这样,如果您有大量数据帧要写入 Excel,则不必手动创建很长的列表。

评论

3赞 Lunalo John 8/30/2019
我不知道为什么这会覆盖第一个工作表
0赞 Skurup 11/25/2020
这确实覆盖了工作表,我和其他人也遇到了这个问题。看这里 -stackoverflow.com/questions/57278418/...
7赞 24lindsey 10/28/2020 #12

我经常使用包装好的里约热内卢进行各种出口。使用 rio,您可以输入一个列表,命名每个选项卡并指定数据集。rio 编译其他 in/out 包,并且为了导出到 Excel,使用 openxlsx。

library(rio)

filename <- "C:/R_code/../file.xlsx"

export(list(sn1 = tempTable1, sn2 = tempTable2, sn3 = tempTable3), filename)

评论

0赞 NickCHK 9/27/2023
希望 SO 有一种方法可以取代高投票但现在过时的答案。他们发帖时是对的,但几乎可以肯定的是,这是现在最好的方法。
5赞 ido klein 6/9/2021 #13

获取一个数据帧并按组编写工作表的整洁方法:

library(tidyverse)
library(xlsx)
mtcars %>% 
  mutate(cyl1 = cyl) %>% 
  group_by(cyl1) %>% 
  nest() %>% 
  ungroup() %>% 
  mutate(rn = row_number(),
         app = rn != 1,
         q = pmap(list(rn,data,app),~write.xlsx(..2,"test1.xlsx",as.character(..1),append = ..3)))