我正在阅读data.table
的文档,并且还注意到此处的一些对话,rbindlist
应该优于rbind
。
我想知道为什么rbindlist
优于rbind
以及rbindlist
在rbind
方面真正优秀的情况?
内存利用方面有什么优势吗?
答案 0 :(得分:145)
rbindlist
是do.call(rbind, list(...))
的优化版本,因使用rbind.data.frame
时速度慢而闻名
显示rbindlist
闪耀的地方的一些问题
Fast vectorized merge of list of data.frames by row
这些基准测试表明它的速度有多快。
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
曾经努力处理factors
,因为已经修复了一个错误:
rbindlist two data.tables where one has factor and other has character type for a column(Bug #2650)
重复列名称存在问题
见 Warning message: in rbindlist(allargs) : NAs introduced by coercion: possible bug in data.table?(Bug #2384)
rbindlist
可以处理lists
data.frames
和data.tables
,并且会返回没有rownames的data.table
你可以使用do.call(rbind, list(...))
进入rownames的混乱局面
见
How to avoid renaming of rows when using rbind inside do.call?
内存方面rbindlist
在C
中实现,内存效率也很高,它使用setattr
按引用设置属性
rbind.data.frame
已在R
中实施,它会进行大量分配,并使用attr<-
(以及class<-
和rownames<-
所有内容(内部)创建创建的data.frame的副本。
答案 1 :(得分:41)
通过v1.9.2
,rbindlist
已经发展了很多,实现了许多功能,包括:
此外,在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倍。