1行しかないデータフレームがあります。これに、rbind を使用して行を追加し始めます
df #mydataframe with only one row
for (i in 1:20000)
{
df<- rbind(df, newrow)
}
私が成長するにつれて、これは非常に遅くなります。何故ですか?どうすればこのタイプのコードを高速化できますか?
1行しかないデータフレームがあります。これに、rbind を使用して行を追加し始めます
df #mydataframe with only one row
for (i in 1:20000)
{
df<- rbind(df, newrow)
}
私が成長するにつれて、これは非常に遅くなります。何故ですか?どうすればこのタイプのコードを高速化できますか?
あなたは地獄の2番目のサークルにいます。つまり、データ構造の事前割り当てに失敗しています。
この方法でオブジェクトを成長させることは、Rでは非常に悪いことです。事前に割り当てて挿入します。
df <- data.frame(x = rep(NA,20000),y = rep(NA,20000))
または、コードを再構築して、この種の行の増分追加を回避します。私が引用したリンクで説明したように、速度が遅い理由は、行を追加するたびに、Rがデータフレームに収まる新しい連続したメモリブロックを見つける必要があるためです。多くのコピー。
例をみました。価値があるのは、データフレームへの行の挿入も非常に遅いというユーザーの主張に同意することです。割り当ての問題がコピーの速度に勝ると予想していたので、何が起こっているのかよくわかりません。誰かがこれを複製するか、以下の結果 (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