我的数据帧只有1行。为此,我开始使用rbind
添加行df #mydataframe with only one row
for (i in 1:20000)
{
df<- rbind(df, newrow)
}
随着我的成长,这变得非常缓慢。这是为什么?以及如何更快地制作此类代码?
答案 0 :(得分:17)
您在2nd circle of hell,即未能预先分配数据结构。
以这种方式增长对象是R中非常糟糕的事情。预先分配和插入:
df <- data.frame(x = rep(NA,20000),y = rep(NA,20000))
或重构您的代码以避免这种增量行的增量。正如在我引用的链接中所讨论的那样,缓慢的原因是每次添加一行时,R需要找到一个新的连续内存块以适应数据帧。很多复制。
答案 1 :(得分:1)
我试了一个例子。对于它的价值,它同意用户的断言,即在数据帧中插入行也非常慢。我不太明白发生了什么,因为我原本预计分配问题会超过复制的速度。任何人都可以复制这个,或解释为什么下面的结果(rbind&lt; appending&lt; insertion)一般都是真的,或者解释为什么这不是一个代表性的例子(例如数据框太小)?
编辑:我第一次忘记将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