合并多个数据帧 - 内存问题

时间:2017-06-12 12:21:26

标签: r dataframe merge

我有多个数据帧(超过25个),包括三列“CompanyName”,“Year”和“VariableX”。 “CompanyNumber”和“Year”的组合是独一无二的。我想将所有这些数据帧合并为一个大数据帧。使用列“CompanyNumber”,“Year”,“Variable from df1”,“Variable from df2”等。每个数据帧包含大约80000行。

data <-  Reduce(function(x, y) merge(x, y, all=TRUE), 
         list(df1, df2, df3, df4, df5, df6, df7, df8, df9, df10, 
         df11, df12, df13, df14, df15, df16, df17, df18, df19, df20, 
         df21, df22, df23, df24, df25))

我尝试了上面的代码,当我有少于8个数据帧但不能处理完整数据时,它可以正常工作。我收到了错误:

  

错误:无法分配大小为126.7 Mb的矢量

我目前使用的是8GB,使用R 64.我已使用gc()rm(list=ls())清除了R的内存。

有没有办法在R中以较少的内存方式合并这些数据帧?

1 个答案:

答案 0 :(得分:1)

这通常是组合不唯一时遇到的问题。这会以指数方式炸毁您的数据框。它可能是数据错误,但也可能是merge不知道要使用哪些变量进行合并的结果。从包含数据框的以下列表开始:

CompNr <- rep(sample(1:8000),10)
Year <- rep(sample(1:10), each = 8000)

dfs <- lapply(1:25,function(i){
  out <- data.frame(CompNr, Year, 
                    X = rnorm(80000, mean = 10*i))
  #make it a bit more difficult for merge by rearranging the rows
  out <- out[sample(nrow(out)),] 
})

在具有6Gb的计算机上运行时没有问题:

out <- Reduce(function(x, y){
  merge(x, y, by = c("CompNr", "Year"),all=TRUE)
  }, dfs)

如果我省略by参数,我会在第3次或第4次合并后耗尽内存。这是因为merge使用两个数据框中名称的交叉作为by变量。在这种情况下,数据框的所有变量都包括X。因此,使用all=TRUE,这相当于简单的rbind。这导致仅在3次合并操作之后具有320.000行的数据帧。你可以很容易地看到你内存不足的原因。

Reduce解决方案仍然会对重复的名称发出大量警告。您可以通过在合并之前重命名变量来解决此问题,或者通过自己手动写出reduce操作并处理其中的名称来解决此问题。例如,使用suffixes参数:

memorymerge <- function(x, by = c("CompNr","Year"), ...){

  out <- x[[1]]
  nx <- length(x[-1])

  for(i in seq(nx) + 1){
    suff <- c("",paste0(".",i))
    out <- merge(out,
                 x[[i]],
                 by = by,
                 suffixes = suff,
                 ...
                 )
  }
  return(out)
}

这会进行合并,并给出以下结果:

> out <- memorymerge(dfs, all = TRUE)
> str(out)
'data.frame':   80000 obs. of  27 variables:
 $ CompNr: int  1 1 1 1 1 1 1 1 1 1 ...
 $ Year  : int  1 10 2 3 4 5 6 7 8 9 ...
 $ X     : num  10.23 9.18 10.51 11.39 10.4 ...
 $ X.2   : num  21.3 19.2 19.4 18.9 20.8 ...
 $ X.3   : num  29.2 29.1 28.9 29.7 30.7 ...
 ...