在R中优化或替代Reduce(merge,list_of_data_frames)

时间:2013-08-06 20:29:01

标签: r performance dataframe reduce

我在列表中有~40K数据帧。每个数据框有7个变量,3个因子和4个数字。作为参考,这是第一个数据框:

 $ a:'data.frame':  4 obs. of  7 variables:
  ..$ x1      : Factor w/ 1 level "a": 1 1 1 1
  ..$ x2        : Factor w/ 4 levels "12345678901234",..: 1 2 3 4
  ..$ x3    : Factor w/ 4 levels "SAMPLE",..: 1 2 3 4
  ..$ x4       : int [1:4] 1 2 3 4
  ..$ x5      : num [1:4] 10 20 30 40
  ..$ x6: int [1:4] 50 60 70 80
  ..$ x7   : num [1:4] 0.5 0.7 0.35 1

我试图将这些合并到一个巨大的数据框中,使用:

Reduce(function(...) merge(..., all=T), df_list)

根据此处的建议:Simultaneously merge multiple data.frames in a list

如果我拿前1000个项目,即

Reduce(function(...) merge(..., all=T), df_list[1:1000])

这会产生所需的结果(将各个数据帧合并为一个)并在37秒内完成。

但是,在整个40K数据框列表上运行Reduce()需要花费过多的时间。我已经让它运行了> 5小时并且它似乎没有完成。

我是否可以使用任何技巧来提高Reduce()的效果,还是有更好的选择?

1 个答案:

答案 0 :(得分:0)

如果你真的需要merge而不仅仅是rbind,你可以先将它们两两合并(1和2,3和4,5和6等),然后合并结果data.frames二乘二,依此类推,直到只剩下一个data.frame。

# One step
merge_some <- function(l, ...) {
  n <- length(l)
  k <- floor(n/2)
  result <- list()
  for(i in 1:k) {
    result[[i]] <- merge(l[[2*i-1]], l[[2*i]], ...)
  }
  if( 2*k < n ) {
    result[[k+1]] <- l[[n]]
  }
  result
}

# Sample data
d <- lapply(1:1000, function(i) {
  r <- data.frame(id = sample(1:100,3), v = rnorm(3))
  names(r)[[2]] <- paste0("v",i)
  r
} )

# Iterate until there is only one data.frame left
while( length(d) > 1 ) {
  d <- merge_some(d, by="id", all=TRUE)
} 

# Result
head(d[[1]])