随着数据框变大,如何防止 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,] &lt;- 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 &lt;- split(data.frame(r), seq_len(nrow(r))) 进行更公平的比较,并在函数内分配。然后使用data.table::rbindlist***.com/a/12718498/1385941 有机会时会做(我还不明白第一句话......如果我理解正确,我认为矩阵分割不应该计入函数 -我假设这些行将在某种迭代过程中一一变为可用) 在函数内分配结果(df &lt;- do.call(rbind, rsplit))(阅读时,我的评论难以理解)。

以上是关于随着数据框变大,如何防止 rbind() 变得非常慢?的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL如何防止表太大?

asp编程中如何设定文本框为数字型

React组件属性部类(propTypes)校验

如何加快rbind?

QT布局管理器 Layout,如何实现窗口最大化时,控件也随着变大。

qt 编程中 怎么让图片随着标签(label)的变大而变大