Chi*_*til 129 r rbind data.table rbindlist
我正在阅读文档,data.table
并且还注意到了一些关于SO的对话,这些对话rbindlist
应该比我更好rbind
.
我想知道为什么rbindlist
比真正优秀的rbind
场景更好?rbindlist
rbind
在内存利用方面有什么优势吗?
mne*_*nel 150
rbindlist
是一个优化版本do.call(rbind, list(...))
,以使用时速度慢而闻名rbind.data.frame
一些问题表明rbindlist
闪耀在哪里
使用do.call和ldply将很长的data.frames(~100万)列表转换为单个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
Run Code Online (Sandbox Code Playgroud)
由于已修复的错误,它过去很难处理factors
:
rbindlist两个data.tables,其中一个有因子,另一个有列的字符类型(Bug#2650)
它有重复的列名称的问题
请参阅 警告消息:在rbindlist(allargs)中:强制引入的NA:data.table中可能出现的错误?(Bug#2384)
rbindlist
可以处理lists
data.frames
和data.tables
,并将返回没有rownames的data.table
你可以使用do.call(rbind, list(...))
see 来获得rownames的混乱
在内存rbindlist
方面实现C
,内存高效,它用于setattr
通过引用设置属性
rbind.data.frame
实现R
,它做了很多分配,并使用attr<-
(class<-
和rownames<-
所有这些将(内部)创建创建的data.frame的副本.
Aru*_*run 43
通过v1.9.2
,rbindlist
进化了很多,实现了许多功能,包括:
SEXPTYPE
在绑定时选择最高列 - 在v1.9.2
关闭FR#2456和Bug#4981时实现.factor
正确处理列 - 首先在v1.8.10
关闭Bug#2650时实现并小心地扩展到绑定有序因子v1.9.2
,关闭FR#4856和Bug#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),因此减慢了很多.我认为这不是唯一的原因.rbind.data.frame
当每个data.frame有许多列并且有许多这样的data.frames要绑定时,检查/匹配列名的实现也会变得更慢(如下面的基准测试所示).
然而,rbindlist
缺少(编辑)某些特征(如检查因子水平或匹配名称)对于它的速度非常小(或没有)rbind.data.frame
.这是因为它们在C中经过精心实施,针对速度和内存进行了优化.
这是一个基准,它突出了有效的绑定,同时匹配列名以及使用rbindlist
的use.names
功能v1.9.3
.数据集由10000个data.frames组成,每个都是10*500.
注意:这个基准已经更新,包括与dplyr
's 的比较bind_rows
library(data.table) # 1.11.5, 2018-06-02 00:09:06 UTC
library(dplyr) # 0.7.5.9000, 2018-06-12 01:41:40 UTC
set.seed(1L)
names = paste0("V", 1:500)
cols = 500L
foo <- function() {
data = as.data.frame(setDT(lapply(1:cols, function(x) sample(10))))
setnames(data, sample(names))
}
n = 10e3L
ll = vector("list", n)
for (i in 1:n) {
.Call("Csetlistelt", ll, i, foo())
}
system.time(ans1 <- rbindlist(ll))
# user system elapsed
# 1.226 0.070 1.296
system.time(ans2 <- rbindlist(ll, use.names=TRUE))
# user system elapsed
# 2.635 0.129 2.772
system.time(ans3 <- do.call("rbind", ll))
# user system elapsed
# 36.932 1.628 38.594
system.time(ans4 <- bind_rows(ll))
# user system elapsed
# 48.754 0.384 49.224
identical(ans2, setDT(ans3))
# [1] TRUE
identical(ans2, setDT(ans4))
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)
在不检查名称的情况下绑定列只需1.3,因为检查列名和绑定只需要1.5秒.与基础解决方案相比,这比基本解决方案快14倍,比dplyr
版本快18倍.
归档时间: |
|
查看次数: |
77844 次 |
最近记录: |