多数の行と多数の列を持つデータフレームがあるとします。
列には名前があります。行には番号で、列には名前でアクセスします。
たとえば、行をループする1つの(おそらく遅い)方法は次のとおりです。
for (i in 1:nrow(df)) {
print(df[i, "column1"])
# do more things with the data frame...
}
別の方法は、個別の列に「リスト」を作成することです(column1_list = df[["column1"]
)、および1つのループでリストにアクセスします。このアプローチは高速かもしれませんが、多くの列にアクセスしたい場合にも不便です。
データフレームの行をループする高速な方法はありますか?高速ループには他のデータ構造が適していますか?
コメントを追跡するのが難しく、これに関するコメントをすでに失ったため、これを完全な答えにする必要があると思います...違いを示す nullglob の例があります中でも、他の例よりもはるかに優れたファミリー関数を適用します。非常に遅いように関数を作成すると、すべての速度が消費され、ループのバリエーションの違いを見つけることができません。しかし、関数を些細なものにすると、ループが物事にどの程度影響するかを確認できます。
また、他の例で未調査のapplyファミリーの一部のメンバーに興味深いパフォーマンス特性があることを付け加えます。最初に、nullglobの相対結果の複製を自分のマシンで表示します。
n <- 1e6
system.time(for(i in 1:n) sinI[i] <- sin(i))
user system elapsed
5.721 0.028 5.712
lapply runs much faster for the same result
system.time(sinI <- lapply(1:n,sin))
user system elapsed
1.353 0.012 1.361
彼はまた、sapplyがはるかに遅いことを発見しました。以下に、テストされていない他のいくつかを示します。
単純に古いデータのマトリックスバージョンに適用...
mat <- matrix(1:n,ncol =1),1,sin)
system.time(sinI <- apply(mat,1,sin))
user system elapsed
8.478 0.116 8.531
したがって、apply()コマンド自体はforループよりも大幅に遅くなります。 (forループは、sin(mat [i、1])を使用しても、それほど遅くなりません。
他の投稿でテストされていないように見えるもう1つのものはtapplyです。
system.time(sinI <- tapply(1:n, 1:n, sin))
user system elapsed
12.908 0.266 13.589
もちろん、この方法でタップリを使用することは決してありません。ほとんどの場合、ユーティリティはそのような速度の問題をはるかに超えています。
最速の方法は、not loop(つまり、ベクトル化された操作)です。ループする必要がある唯一のインスタンスの1つは、依存関係がある場合です(つまり、1つの反復が別の反復に依存します)。それ以外の場合は、ループ外で可能な限りベクトル化された計算を実行してください。
ループする必要があるdoの場合、for
ループを使用することは、本質的に他のもの(lapply
少し速くなりますが、 他のapply
関数はfor
とほぼ同じ速度になる傾向があります )。
Data.framesは本質的に列ベクトルのリストであるという事実を利用して、do.callを使用して、data.frameの各列に列数のアリティを持つ関数を適用できます(リストの「圧縮」に似ています)他の言語で)。
do.call(paste, data.frame(x=c(1,2), z=c("a","b"), z=c(5,6)))