【问题标题】:Read multiple xlsx files with multiple sheets into one R data frame将具有多张工作表的多个 xlsx 文件读入一个 R 数据帧
【发布时间】:2016-07-05 07:33:54
【问题描述】:

我一直在阅读有关如何读取多个 xlsx 文件并将其组合到一个 R 数据帧中的信息,并且遇到了一些非常好的建议,例如 How to read multiple xlsx file in R using loop with specific rows and columns,但到目前为止不适合我的数据集。

我希望 R 读取具有多个工作表的多个 xlsx 文件。所有工作表和文件都具有相同的列,但长度不同,应排除 NA。我想跳过前 3 行,只取 1:6、8:10、12:17、19 列。

到目前为止我尝试过:

file.list <- list.files(recursive=T,pattern='*.xlsx')

dat = lapply(file.list, function(i){
    x = read.xlsx(i, sheetIndex=1, sheetName=NULL, startRow=4,
              endRow=NULL, as.data.frame=TRUE, header=F)
# Column select 
    x = x[, c(1:6,8:10,12:17,19)]
# Create column with file name  
    x$file = i
# Return data
    x
  })

  dat = do.call("rbind.data.frame", dat)

但这只会占用每个文件的第一张表

有谁知道如何将所有工作表和文件放在一个 R 数据框中?

另外,对于大型数据集,您会推荐哪些软件包?到目前为止,我尝试了 readxl 和 XLConnect。

【问题讨论】:

  • 您已明确要求只提供函数中的第一张工作表:x = read.xlsx(i, sheetIndex=1,....)
  • 另外,如果您希望优化大型数据集的速度,则值得查找 data.table 包。除其他外,它的 fread 函数允许您只读取您需要的列,而不是读取所有列然后进行子集化。但我不确定它是否适用于 .xlsx 文件。
  • 你的 lapply 已经循环了文件,你需要在工作表上再循环一次才能得到你想要的。
  • 感谢您的建议。你知道是否有办法用 read.xlsx 要求所有工作表?

标签: r excel xlsx readxl openxlsx


【解决方案1】:

openxlsx 解决方案:

filename <-"myFilePath"

sheets <- openxlsx::getSheetNames(filename)
SheetList <- lapply(sheets,openxlsx::read.xlsx,xlsxFile=filename)
names(SheetList) <- sheets

【讨论】:

  • 我认为这是一个更快更优雅的解决方案!!谢谢!
【解决方案2】:

我会使用这样的嵌套循环来遍历每个文件的每个工作表。 它可能不是最快的解决方案,但它是最简单的。

require(xlsx)    
file.list <- list.files(recursive=T,pattern='*.xlsx')  #get files list from folder

for (i in 1:length(files.list)){                                           
  wb <- loadWorkbook(files.list[i])           #select a file & load workbook
  sheet <- getSheets(wb)                      #get sheet list

  for (j in 1:length(sheet)){ 
    tmp<-read.xlsx(files.list[i], sheetIndex=j, colIndex= c(1:6,8:10,12:17,19),
                   sheetName=NULL, startRow=4, endRow=NULL,
                   as.data.frame=TRUE, header=F)   
    if (i==1&j==1) dataset<-tmp else dataset<-rbind(dataset,tmp)   #happend to previous

  }
}

您可以在加载阶段之后清除 NA 值。

【讨论】:

  • 非常感谢!这对我来说并不好退出。我收到警告:charToDate(x) 中的错误:字符串不是标准的明确格式
  • 这听起来像是在加载所有内容后格式化日期变量时会出现的错误。有了这个错误,您通常必须操纵您的日期变量以使其成为标准格式。见this post
  • 它也可能来自 R 试图猜测列的类别并错误地认为它是一个日期(参见 ? read.xlsx)。在这种情况下,我建议使用 colClasses 参数来强制将所有列作为字符串加载。并在所有内容加载后清理数据(给出正确的类,NA..)。
  • 您可以用sapply 函数替换第二个循环,而不是使用两个循环,例如do.call("rbind", sapply(sheet, function(x, y) read.xlsx(y, x), files.list[i]))
  • 不应该 files.list 在你的 for 循环中由 file.list 代替吗?
【解决方案3】:

这是一个 tidyversereadxl 驱动选项,它返回一个数据框,其中包含文件列和每个文件的工作表名称。

在此示例中,并非每个文件都具有相同的工作表或列; test2.xlsx 只有一张,test3.xlsx sheet1 没有 col3。

library(tidyverse)
library(readxl)

dir_path <- "~/test_dir/"         # target directory path where the xlsx files are located. 
re_file <- "^test[0-9]\\.xlsx"    # regex pattern to match the file name format, in this case 'test1.xlsx', 'test2.xlsx' etc, but could simply be 'xlsx'.

read_sheets <- function(dir_path, file){
  xlsx_file <- paste0(dir_path, file)
  xlsx_file %>%
    excel_sheets() %>%
    set_names() %>%
    map_df(read_excel, path = xlsx_file, .id = 'sheet_name') %>% 
    mutate(file_name = file) %>% 
    select(file_name, sheet_name, everything())
}

df <- list.files(dir_path, re_file) %>% 
  map_df(~ read_sheets(dir_path, .))

# A tibble: 15 x 5
   file_name  sheet_name  col1  col2  col3
   <chr>      <chr>      <dbl> <dbl> <dbl>
 1 test1.xlsx Sheet1         1     2     4
 2 test1.xlsx Sheet1         3     2     3
 3 test1.xlsx Sheet1         2     4     4
 4 test1.xlsx Sheet2         3     3     1
 5 test1.xlsx Sheet2         2     2     2
 6 test1.xlsx Sheet2         4     3     4
 7 test2.xlsx Sheet1         1     3     5
 8 test2.xlsx Sheet1         4     4     3
 9 test2.xlsx Sheet1         1     2     2
10 test3.xlsx Sheet1         3     9    NA
11 test3.xlsx Sheet1         4     7    NA
12 test3.xlsx Sheet1         5     3    NA
13 test3.xlsx Sheet2         1     3     4
14 test3.xlsx Sheet2         2     5     9
15 test3.xlsx Sheet2         4     3     1

【讨论】:

    【解决方案4】:

    这个“rio”包的另一个解决方案:

    library("rio")
    
    # import and rbind all worksheets
    DT <- import_list(SINGLE_XLSX_PATH, rbind = TRUE)
    

    来源:rdrr.io

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 2019-04-16
      • 1970-01-01
      • 1970-01-01
      • 2012-06-28
      • 1970-01-01
      • 1970-01-01
      • 2013-11-29
      • 1970-01-01
      相关资源
      最近更新 更多