R数据表内存高效rbindlist

3
我希望您能以一种内存高效的方式将多个数据表进行行绑定。更准确地说,我希望能够逐个绑定它们,并在此过程中释放内存,以便在我的内存只有大小为(n+1)*k时,可以连接大小为k的n个数据表。
我编写了以下函数以实现此目的:
rbindlistOneByOne <- function(l, use.names=FALSE, fill=FALSE, idcol=NULL, verbose = F) {
  ll <- length(l)
  # Handle empty lists
  if(ll <= 0) stop("rbindlistOneByOne : empty list")
  if(ll <= 1) return(l[[1]])
  # Handle normal lists (ll > 2)
  current <- l[[1]]
  res <- current
  l[1] <- NULL
  rm(current); gc()
  for(i in 2:ll) {
    current <- l[[1]]
    res <- rbindlist(list(res, current), use.names = use.names, fill = fill, idcol = idcol)
    l[1] <- NULL
    rm(current); gc()
  }
  return(res)
}

现在的问题是,即使我认为这个函数应该是内存高效的,但事实上并不是

你知道为什么吗?是因为rm命令不会释放内存,导致被称为“current”的data.table仍然占用着内存。


如果使用 data.table 内置的 rbindlist() 函数会发生什么? - Uwe
2
l <- rbindlist(l) 应该非常高效,因为它不会进行深度复制。 - Roland
1
gc() 不释放内存。在 R 中,内存分配是确定性的,但内存释放是随机的。在 R 中无法实现你想要做的事情。最好的方式是使用 rbindlist,它是最节省内存的方法。 - JRR
1
数据表是如何创建或加载的?在处理链中是否有将表绑定到更早阶段的机会? - Uwe
(1) 是的,我做了。 (2) 我不知道这个函数,我会尽快阅读相关资料。 (3) 它们是在 foreach 循环中创建的,因此要以不同的方式重写可能会很困难。 谢谢你的帮助 :) - VeilleData
显示剩余4条评论
1个回答

1
你想做的事情是不可能的。在R中,内存释放是随机的,不能控制。使用gc()可能会释放内存,也可能不会,而且用户无法控制。
http://adv-r.had.co.nz/memory.html中可以看到:
尽管您可能已经在其他地方读到过这个信息,但您永远不需要自己调用gc()。每当R需要更多空间时,R将自动运行垃圾回收; 如果您想知道何时发生这种情况,请调用gcinfo(TRUE)。您可能想要调用gc()的唯一原因是要求R将内存返回给操作系统。但是,即使如此,也可能没有任何效果:旧版本的Windows没有办法让程序将内存返回给操作系统。
此外,调用gc非常缓慢。这里是一个对于包含1000个10行表格的列表进行函数测试的基准测试,分别测试了有和没有调用gc的情况:
  • 没有gc:8毫秒
  • gc:7秒

rbindlist 是绑定 data.table 最高效的方式。


谢谢。我将寻找在ROM中而非内存中的rbind解决方案。 - VeilleData

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接