随着数据框变大,如何防止 rbind() 变得非常慢?
Posted
技术标签:
【中文标题】随着数据框变大,如何防止 rbind() 变得非常慢?【英文标题】:How can I prevent rbind() from geting really slow as dataframe grows larger? 【发布时间】:2013-01-19 13:53:03 【问题描述】:我有一个只有 1 行的数据框。为此,我开始使用 rbind 添加行
df #mydataframe with only one row
for (i in 1:20000)
df<- rbind(df, newrow)
随着我的成长,这变得非常缓慢。这是为什么?以及如何使这种类型的代码更快?
【问题讨论】:
因为你在second circle of hell。 @joran,这是一个答案,而不是评论。 【参考方案1】:您在2nd circle of hell,即未能预先分配数据结构。
以这种方式增长对象在 R 中是一件非常非常糟糕的事情。预分配和插入:
df <- data.frame(x = rep(NA,20000),y = rep(NA,20000))
或重组您的代码以避免这种增量添加行。正如我在引用的链接中所讨论的那样,速度缓慢的原因是每次添加一行时,R 都需要找到一个新的连续内存块来适应数据框。大量复制。
【讨论】:
太棒了。感谢您的提示。 所以我重新分配了数据帧并开始在其中插入 1 行数据帧 (df[j] @Mark 是的,就像我说的,这种事情有点不像 R。修改对象仍需要对整个对象进行一定量的复制。您真的要在每次添加行时复制整个数据框吗?可能不是。使用lapply
生成每行的列表,然后使用do.call(rbind,...)
将它们拼接在一起。但除此之外,鉴于您提供的信息,该解决方案需要更多的重构,而我无法提供帮助。
荣誉。非常感谢。我对在这里使用 apply 进行了很多思考,但是问题的形状如此奇怪,我的大脑无法理解它的正确功能形式:) 感谢您的帮助
我有点惊讶df[j,] <- newrow
也很慢,尤其是在运行后期它会变慢。我可以理解它需要一些数据帧复制,但它应该比第二个地狱循环方法快几个数量级......【参考方案2】:
我尝试了一个例子。对于它的价值,它同意用户的断言,即在数据框中插入行也很慢。我不太明白发生了什么,因为我预计分配问题会超过复制速度。任何人都可以复制这个,或者解释为什么下面的结果(rbind
编辑:我第一次忘记将hell2fun
中的对象初始化为数据帧,所以代码是在做矩阵运算而不是数据帧运算, 更快。如果有机会,我会将比较扩展到数据框与矩阵。不过,第一段中的定性断言仍然成立。
N <- 1000
set.seed(101)
r <- matrix(runif(2*N),ncol=2)
## second circle of hell
hell2fun <- function()
df <- as.data.frame(rbind(r[1,])) ## initialize
for (i in 2:N)
df <- rbind(df,r[i,])
insertfun <- function()
df <- data.frame(x=rep(NA,N),y=rep(NA,N))
for (i in 1:N)
df[i,] <- r[i,]
rsplit <- as.list(as.data.frame(t(r)))
rbindfun <- function()
do.call(rbind,rsplit)
library(rbenchmark)
benchmark(hell2fun(),insertfun(),rbindfun())
## test replications elapsed relative user.self
## 1 hell2fun() 100 32.439 484.164 31.778
## 2 insertfun() 100 45.486 678.896 42.978
## 3 rbindfun() 100 0.067 1.000 0.076
【讨论】:
我建议使用rsplit <- split(data.frame(r), seq_len(nrow(r)))
进行更公平的比较,并在函数内分配。然后使用data.table::rbindlist
***.com/a/12718498/1385941
有机会时会做(我还不明白第一句话......如果我理解正确,我认为矩阵分割不应该计入函数 -我假设这些行将在某种迭代过程中一一变为可用)
在函数内分配结果(df <- do.call(rbind, rsplit))
(阅读时,我的评论难以理解)。以上是关于随着数据框变大,如何防止 rbind() 变得非常慢?的主要内容,如果未能解决你的问题,请参考以下文章