为什么rbindlist比rbind“更好”?

时间:2013-03-28 03:05:36

标签: r data.table rbind rbindlist

我正在阅读data.table的文档,并且还注意到此处的一些对话,rbindlist应该优于rbind

我想知道为什么rbindlist优于rbind以及rbindlistrbind方面真正优秀的情况?

内存利用方面有什么优势吗?

2 个答案:

答案 0 :(得分:145)

rbindlistdo.call(rbind, list(...))的优化版本,因使用rbind.data.frame时速度慢而闻名


它真正优秀的地方

显示rbindlist闪耀的地方的一些问题

Fast vectorized merge of list of data.frames by row

Trouble converting long list of data.frames (~1 million) to single data.frame using do.call and ldply

这些基准测试表明它的速度有多快。


rbind.data.frame很慢,原因是

rbind.data.frame会进行大量检查,并会按名称进行匹配。 (即rbind.data.frame将说明列可能处于不同的顺序,并按名称匹配),rbindlist不执行此类检查,并将按位置加入

例如

do.call(rbind, list(data.frame(a = 1:2, b = 2:3), data.frame(b = 1:2, a = 2:3)))
##    a b
## 1  1 2
## 2  2 3
## 3  2 1
## 4  3 2

rbindlist(list(data.frame(a = 1:5, b = 2:6), data.frame(b = 1:5, a = 2:6)))
##     a b
##  1: 1 2
##  2: 2 3
##  3: 1 2
##  4: 2 3

rbindlist

的其他一些限制

曾经努力处理factors,因为已经修复了一个错误:

rbindlist two data.tables where one has factor and other has character type for a columnBug #2650

重复列名称存在问题

Warning message: in rbindlist(allargs) : NAs introduced by coercion: possible bug in data.table?Bug #2384


rbind.data.frame rownames可能令人沮丧

rbindlist可以处理lists data.framesdata.tables,并且会返回没有rownames的data.table

你可以使用do.call(rbind, list(...))进入rownames的混乱局面 见

How to avoid renaming of rows when using rbind inside do.call?


内存效率

内存方面rbindlistC中实现,内存效率也很高,它使用setattr按引用设置属性

rbind.data.frame已在R中实施,它会进行大量分配,并使用attr<-(以及class<-rownames<-所有内容(内部)创建创建的data.frame的副本。

答案 1 :(得分:41)

通过v1.9.2rbindlist已经发展了很多,实现了许多功能,包括:

  
      
  • 在绑定时选择最高SEXPTYPE列 - 在v1.9.2关闭FR #2456Bug #4981中实施。
  •   
  • 正确处理factor列 - 首先在v1.8.10关闭Bug #2650中实施,并在v1.9.2中仔细扩展到绑定有序因素,关闭FR #4856Bug #5019
  •   

此外,在v1.9.2中,rbind.data.table也获得了fill参数,允许通过填充在R中实现的缺失列进行绑定。

现在在v1.9.3中,对这些现有功能进行了更多改进:

  
      
  • rbindlist获得一个参数use.names,默认情况下为FALSE以便向后兼容。
  •   
  • rbindlist也会获得一个参数fill,默认情况下也是FALSE以便向后兼容。
  •   
  • 这些功能都是用C语言实现的,并且在添加功能时要小心写,以免速度受损。
  •   
  • 由于rbindlist现在可以按名称匹配并填充缺失的列,rbind.data.table现在只需调用rbindlist。唯一的区别是use.names=TRUE默认为rbind.data.table,以便向后兼容。
  •   

rbind.data.frame减慢了很多,主要是由于副本(@mnel指出的)可以避免(通过转移到C)。我认为这不是唯一的原因。当每个data.frame有很多列时,rbind.data.frame中检查/匹配列名的实现也会变慢,并且有许多这样的data.frames要绑定(如下面的基准测试所示)。

然而,rbindlist缺少(编辑)某些特征(如检查因子水平或匹配名称)对于它的速度非常小(或没有),因为它比rbind.data.frame快。这是因为它们在C中经过精心实施,针对速度和内存进行了优化。

这是一个基准,通过rbindlist使用use.names的{​​{1}}功能突出显示有效绑定,同时按列名称进行匹配。数据集由10000个data.frames组成,每个都是10 * 500。

注意:此基准测试已更新,以包含与v1.9.3的{​​{1}}

的比较
dplyr

在没有检查名称的情况下绑定列只需1.3,因为检查列名和绑定只需要1.5秒。与基本解决方案相比,它比bind_rows版本快14倍,速度快18倍。