webdevqa.jp.net

Rのforループからデータフレームへの書き込み

ループからRのデータフレームに書き込もうとしています。たとえば、次のようなループ>

for (i in 1:20) {
print(c(i+i,i*i,i/1))}

また、3つの値の各行を3つの列を持つデータフレームに書き込むため、各反復で新しい行が実行されます。 ncol = 3で行で満たされた行列を使用してみましたが、ループから最後の項目しか取得できません。

ありがとう。

16
CCID

あなたはrbindを使うことができます:

d <- data.frame()
for (i in 1:20) {d <- rbind(d,c(i+i, i*i, i/1))}
23
Karsten W.

別の方法は

do.call("rbind", sapply(1:20, FUN = function(i) c(i+i,i*i,i/1), simplify = FALSE))


     [,1] [,2] [,3]
 [1,]    2    1    1
 [2,]    4    4    2
 [3,]    6    9    3
 [4,]    8   16    4
 [5,]   10   25    5
 [6,]   12   36    6

simplify = FALSEを指定しない場合は、tを使用して結果を転置する必要があります。これは大きな構造物では退屈な場合があります。

このソリューションは、データセットが大きい場合や、これを何度も繰り返す必要がある場合に特に便利です。

この「スレッド」でソリューションのタイミングをいくつか提供します。

> system.time(do.call("rbind", sapply(1:20000, FUN = function(i) c(i+i,i*i,i/1), simplify = FALSE)))
   user  system elapsed 
   0.05    0.00    0.05 

> system.time(ldply(1:20000, function(i)c(i+i, i*i, i/1)))
   user  system elapsed 
   0.14    0.00    0.14 

> system.time({d <- matrix(nrow=20000, ncol=3) 
+ for (i in 1:20000) { d[i,] <- c(i+i, i*i, i/1)}})
   user  system elapsed 
   0.10    0.00    0.09 

> system.time(ldply(1:20000, function(i)c(i+i, i*i, i/1)))
   user  system elapsed 
  62.88    0.00   62.99 
10
Roman Luštrik

すべての値が同じ型で、行数がわかっている場合は、次のように行列を使用できます(これは非常に高速です)。

d <- matrix(nrow=20, ncol=3) 
for (i in 1:20) { d[i,] <- c(i+i, i*i, i/1)}

データフレームが必要な場合は、rbind(別の答えが示すように)、または次のようなパッケージplyrの関数を使用できます。

library(plyr)
ldply(1:20, function(i)c(i+i, i*i, i/1))
6
cafe876

Forループには副作用があるため、これを行う通常の方法は、ループの前に空のデータフレームを作成し、各反復でそれに追加することです。それを正しいサイズにインスタンス化してから、各反復でi番目の行に値を割り当てるか、追加してrbind()を使用して全体を再割り当てできます。

前者のアプローチは、大規模なデータセットのパフォーマンスが向上します。

6
Shane