11

1行しかないデータフレームがあります。これに、rbind を使用して行を追加し始めます

df #mydataframe with only one row
for (i in 1:20000)
{
    df<- rbind(df, newrow)

}

私が成長するにつれて、これは非常に遅くなります。何故ですか?どうすればこのタイプのコードを高速化できますか?

4

2 に答える 2

21

あなたは地獄の2番目のサークルにいます。つまり、データ構造の事前割り当てに失敗しています。

この方法でオブジェクトを成長させることは、Rでは非常に悪いことです。事前に割り当てて挿入します。

df <- data.frame(x = rep(NA,20000),y = rep(NA,20000))

または、コードを再構築して、この種の行の増分追加を回避します。私が引用したリンクで説明したように、速度が遅い理由は、行を追加するたびに、Rがデータフレームに収まる新しい連続したメモリブロックを見つける必要があるためです。多くのコピー。

于 2013-02-04T19:32:38.970 に答える
1

例をみました。価値があるのは、データフレームへの行の挿入も非常に遅いというユーザーの主張に同意することです。割り当ての問題がコピーの速度に勝ると予想していたので、何が起こっているのかよくわかりません。誰かがこれを複製するか、以下の結果 (rbind < 追加 < 挿入) が一般的に正しい理由を説明できますか、またはこれが代表的な例ではない理由 (例: データフレームが小さすぎる) を説明できますか?

edit : 初めてオブジェクトを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 
于 2013-02-04T22:22:40.403 に答える