合并Data.frames显示错误:无法分配大小为1.4 Gb的向量

时间:2017-01-25 11:07:39

标签: r memory-management dataframe merge

我的RAM是4 GB,我使用的是64位Windows和R.我希望在公共密钥列(日期)的基础上合并大约25个数据帧。我在互联网和各种堆栈溢出论坛上搜索。但是,我收到错误“错误:无法分配大小为x Gb的向量”。 data.frames看起来像

A <- data_frame(Date = c("1/1/1990","1/2/1990","1/3/1990"), MXAR = c(342.369,342.369,525.528 ))
B <- data_frame(Date = c("11/30/2009","12/1/2009","12/2/2009"), MXBD = c(1000,1007.13,998.55 ))
C <- data_frame(Date = c("6/1/2005","6/2/2005","6/6/2005"), MXBH = c(1209.21,1205.74,1195.33 ))

我有大约25个数据框架,如A,B和C(每个都有大约3000行)。我在堆栈溢出时使用如下所示的解决方案。 A,B和C data.frames显示最后一行中的NA。但是,他们继续抛出错误。请帮助。 filenames = list.files(path = path,full.names = TRUE)#files文件类型为A,B和C#在上面讨论

datalist = lapply(filenames, function(x){read_excel(x,sheet=1)})
df6<-datalist %>% Reduce(function(dtf1,dtf2) inner_join(dtf1,dtf2,by="Date"), .)

file_list <- list.files()

for (file in file_list)
{


  # if the merged dataset does exist, append to it
  if (exists("dataset")){
    temp_dataset <-read_excel(file)

    dataset<-merge.data.frame(dataset, temp_dataset, by=c('Date'))
    rm(temp_dataset)
  }
# if the merged dataset doesn't exist, create it
  if (!exists("dataset")){
    dataset <- read_excel(file)

  }
}

reshape::merge_all(datalist, by="Date")

运行时

datalist = lapply(filenames, function(x){data.table(read_excel(x,sheet=1), key="Date")})

该程序会抛出许多警告,例如

In read_xlsx_(path, sheet, col_names = col_names, col_types = col_types,             ... :
  [1601, 1]: expecting date: got '[NULL]'

A,B和C data.frames显示最后一行中的NA。有没有办法在上面的代码行中删除这些NA,然后运行该程序。可以消除错误。

2 个答案:

答案 0 :(得分:2)

好像你的描述和错误有几个问题。这可能不是一个简单的代码解决方案,而是一系列令人困惑的问题,所以我会尽力而不会看到你的代码崩溃并烧毁自己。

你需要非常狡猾才能在循环中完成所有事情而不会造成膨胀。

如果要合并日期,首先要做的是使用str(df)检查每个框架(合并之前),看看日期字段的结构和数据类型都是相同的。日期时间作为因素而有时甚至是字符数据并不罕见。

如果它们不完全相同,则在合并循环中创建一个函数(在循环中运行之前单独测试)以遍历每个文件$ date字段并转换为统一的日期时间,如POSIXct。

你可能需要使用if语句来判断它们是日期,数字,字符或因子,然后对每个语句应用正确的as.,但如果你想让合并工作,绝对必须完全确切。 (示例:as.dateas.POSIXct

如果有任何因素需要嵌套转换,请不要使用怪异的强制措施。您可以使用:

as.POSIXct(as.character(df$col), %m/%d/%Y)

将新文件合并到大文件后,使用rm()(文件名在rm语句的括号内),以清除环境中新导入的文件,仅保留合并文件

然后,您需要运行gc()以从内存中清除已删除的文件。如果不这样做,它可能会在内存中持续存在并影响下一个文件。

有些事情需要注意,在许多重复过程中,R数据帧在内存中存在2-4个副本。如果这些文件很大,并且你没有用rm(df)和gc()清除它们,你肯定会遇到问题。

此外,在使用Excel文件时,您很可能使用具有自己的堆并占用内存的JAVA接口。并且R不会告诉它的JAVA工作人员像任何人想要的那样有效地清除,系统只有在它无法运行时才会这样做,所以你最终会有一些不断缩小的可访问内存用于合并。

确保在合并后在循环中包含rm()和gc()。因为有许多文件,所以如果当前迭代失败,请考虑使用print(yourfilename.type)语句返回失败的合并名称和next()语句以转到下一个文件。

通过这种方式,您可以在点击文件后保持循环运行,但它不会合并,因此您可以构建失败文件列表并开始追查它们的不同之处以解决问题。有时在excel中更容易这样做(如果列需要6个数字宽,前面的零,请手动格式化)。

AND ...如果您能够使用CSV而不是Excel文件(如果它们是单个工作表,而不是分层)转换它们,您将释放RAM。或者考虑编写一个脚本将工作簿转换为多个工作表并将它们保存为csv文件以修剪文件中的内容并限制您对JUGS和Java的处理依赖性。

可能不是你想要的答案,但这是一个开始。

答案 1 :(得分:0)

将数据从excel文件导入R程序。这会在最后一行中创建很多NA。通过使用下面的代码删除NA,节省了大量内存并有助于有效地合并data.frames。这些代码一次性从data.frames列表中删除NA。

filenames=list.files(path=path, full.names=TRUE)
datalist4 = lapply(filenames, function(x){read_excel(x,sheet=1)})
str(datalist4)
datalist5<-lapply(datalist4, na.omit)#removing NA row from each data.frames