Answers:
rbindlist是的优化版本do.call(rbind, list(...)),使用时速度较慢rbind.data.frame
一些问题可以显示出哪里rbindlist发光
使用do.call和ldply将一长串data.frames(〜1百万)转换为单个data.frames时出现问题
这些基准测试显示了测试速度。
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两个data.tables,其中一个具有因数,另一个具有一列的字符类型(错误#2650)
列名重复有问题
请参阅 警告消息:在rbindlist(allargs)中:强制引入的NA:在data.table中可能存在错误?(错误#2384)
rbindlist可以处理lists data.frames和data.tables,并且将返回不带行名的data.table
您可以使用do.call(rbind, list(...))
see 混淆行名
在rbindlist中实现内存方面C,因此内存效率高,它用于setattr通过引用设置属性
rbind.data.frame在中实现R,它会进行大量分配,并且会使用attr<-(class<-并且rownames<-所有这些都将(内部)创建所创建data.frame的副本。
DF = data.frame(a=1:3); .Internal(inspect(DF)); tracemem(DF); attr(DF,"test") <- "hello"; .Internal(inspect(DF))。
rbind.data.frame具有特殊的“劫持”逻辑-当其第一个参数为时data.table,它会调用.rbind.data.table,这会进行一点检查,然后在rbindlist内部调用。因此,如果您已经有data.table要绑定的对象,则rbind和之间的性能差异可能很小rbindlist。
rbindlist它现在可以按名称匹配(use.names=TRUE),还可以填充缺少的列(fill=TRUE)。我已经更新了这个,这个和这个帖子。您介意编辑此文件吗?如果可以,可以吗?两种方法对我来说都很好。
dplyr::rbind_list也非常相似
通过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.frame时也可能会变慢(如下面的基准所示)。
但是,rbindlist缺少某些功能(例如检查因子水平或匹配名称)对它的影响很小(或没有),因此比快rbind.data.frame。这是因为它们是用C精心实现的,并且针对速度和内存进行了优化。
这里有一个基准,突出了高效的结合,同时通过列名的匹配,以及使用rbindlist的use.names功能v1.9.3。数据集由10000个数据帧组成,每个数据帧的大小为10 * 500。
注意:这个测试已经更新到包括比较dplyr的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
这样,不检查名称就绑定列仅花费1.3,而检查列名称和适当地绑定仅花费1.5秒。与基本解决方案相比,它的速度快了14倍,比dplyr的版本快18倍。
attr<-,class<-(我认为)rownames<-全部修改到位。