读取多个xlsx文件并合并到R中的数据框中

时间:2017-02-22 01:04:44

标签: r loops merge xlsx

我正在编写代码:

  • 阅读文件夹列表

  • 使用列表中的某些文本元素对文件夹进行排序和提取

  • 从每个文件夹中获取完整的文件名

  • 在每个文件中找到标签/表格

  • 在我的嵌套文件列表中循环/ lapply read.xlsx()

最终目标是从各自的文件夹中读取各自文件中的所有标签/表格,同时创建列以确定它们来自哪个标签/表格以及它们来自哪个文件夹,以及然后将它们合并在一起。

我在excel文件中阅读的首选包是“ openxlsx ”。

这是获取文件夹和文件的代码:

path<- "/Users/jackserna/Google Drive/Folder"
dataFolders<- list.files(path)
dataFolders<- sort(dataFolders[starts_with(match = "FY", vars = dataFolders)])
files<- lapply(lapply(dataFolders, FUN = function(x){
     paste(path,x,sep = "/")
     }), FUN = function(x){
          list.files(x, pattern = "*.xlsx", full.names = TRUE)
 })

我无法为我的所有文件和所有工作表循环/应用读取功能。我会阅读不超过1个文件夹,必须重复。我使用了this post ...

中的一些代码
data.to.merge <- lapply(lapply(files[[1]], FUN = function(x){
     read.xlsx(x, sheet = 3, cols = 1:5)
}), na.omit)
merged.daata <- Reduce(function(...) merge(..., all = T), data.to.merge) 

但是,这种方法不允许我将工作表名称作为我读入的每个工作表的额外列添加。这种方法假设第3页有数据,但令我沮丧的是这些文件不是这种情况。数据分散在工作表中,必须忽略某些工作表才能合并。

试图抓住所有床单并解析出我不想要的床单,这就是我们所做的:

allsheets<- list()
for(i in files){
  for(j in i){
    sheets<- getSheetNames(j)
    allsheets<- cbind(allsheets,sheets)
  }
}

但这已经变成了一个能够用于阅读和合并的噩梦。

如何让R了解我想要完成的任务?

3 个答案:

答案 0 :(得分:1)

我无法解决这个特定的数据清理噩梦,但在准备明年我对文件结构做了一些更改。我发现data.table包对于将嵌套列表引入像数据帧这样的东西非常有用。

请注意,以下所有数据仅从1个指定的工作表名称(或编号)中读取。

### Get list of folder names
dataFolders<- list.files(path = path)
dataFolders<- sort(dataFolders[starts_with(match = "FY", vars = dataFolders)])

### Get list of files for each regional folder
files<- lapply(lapply(dataFolders, FUN = function(x){
     paste(path,x,sep = "/")}), FUN = function(x){
          list.files(x, pattern = "*.xlsx", full.names = TRUE)
})

dataPrep<- lapply(files, FUN = function(x){
     lapply(lapply(x, FUN = function(x){
          read.xlsx(x, sheet = "Sheet Name", cols = 1:6)}), na.omit)
})
transform<- rbindlist(lapply(dataPrep, FUN = function(x){
     rbindlist(x, use.names = TRUE)
}), use.names = TRUE) 

没有噩梦解决方案,但成为数据录入的标准。

答案 1 :(得分:0)

我会对你的单独功能保持分离,这样你就可以追踪出错的地方,并且在你的Excel包之后给R一个机会来清理,这将是内存密集型的。如果你将所有东西都推到一个命令中,它就会陷入困境并崩溃。

使用您喜欢的软件包将sheet_list读入内存之后,应该这样做:

for (i in sheet_list({
new_sheet<- your_read_command(sheet_list[i])
     #subsitute using whatever reader package command you use likexlConnect or xlsx
new_sheet$sheetname<- i #(adding the column with sheet name prior to binding)
data<-rbind(data, new_sheet)
rm(new_sheet)
gc()}`

rm()&amp; gc()在这里非常重要。您会发现所有Excel阅读器都是基于JARS的,而HOG内存会使您的系统崩溃。绑定数据后删除每个对象,然后进行垃圾收集以防止爬行停止或平坦崩溃!

我用CSV测试了这些部件并且它可以工作......你现在必须使用Excel软件包并且可能稍微调整一下。如果您需要帮助发表评论......

OH和...创建data&lt; -data.frame()`并在进入循环之前为其分配所有列名...这将为循环提供绑定的东西!

答案 2 :(得分:0)

我还可以推荐包readxl。它可能无法检测工作表中的工作表数量,但您可以在使用XLConnect查找工作表后使用它。

library(data.table)
my.monthly.excel.files <-  "../../../../../../Documents/Output/Monthly/"
my.file.list <- data.table(File.Name = list.files(path = my.monthly.excel.files , pattern = ".xlsx$" , recursive = FALSE, include.dirs = FALSE))
rbindlist(lapply(my.file.list[,File.Name], function(file){print(file); read_excel(path = paste0(my.monthly.excel.files, file), sheet = "sheet_name")}))

为了摆脱警告,我将每个要导入的列的列类型定义为文本,数字或日期。