为了账号安全,请及时绑定邮箱和手机立即绑定

为什么rbindlist比rbind“更好”?

为什么rbindlist比rbind“更好”?

慕容708150 2019-10-05 13:58:47
我正在阅读data.tableSO的文档,并且从中进行的一些对话中也发现,SO rbindlist可能比SO 更好rbind。我想知道为什么是rbindlist优于rbind以及其中场景rbindlist的确有过人之处过rbind?在内存利用率方面有什么优势吗?
查看完整描述

3 回答

?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

通过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时,检查/匹配in中列名的实现也可能会变慢(如下面的基准所示)。


但是,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倍。


查看完整回答
反对 回复 2019-10-05
?
BIG阳

TA贡献1859条经验 获得超6个赞

rbind.data.frame具有特殊的“劫持”逻辑-当其第一个参数为时data.table,它将调用.rbind.data.table,它会进行一点检查并在rbindlist内部进行调用。因此,如果您已经有data.table要绑定的对象,则rbind和之间的性能差异可能很小rbindlist

查看完整回答
反对 回复 2019-10-05
  • 3 回答
  • 0 关注
  • 1982 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信