2012-03-05 15 views
3

ダブルループは私が好きではないだけでなく、3200レコードと1090個の変数を約12回繰り返して実行しているので、コンピュータで実行するのに14日かかります。レコードの結果とダブルループの比較

小さい再現可能ビット。 2つのレコード間で同じ列にある数値の数を確認します。NAは含まれません。次に、結果を元のデータフレームに添付します。

y <- data.frame(c(1,2,1,NA,NA),c(3,3,3,4,NA),c(5,4,5,7,7),c(7,8,7,9,10)) 
resultdf <- NULL 
for(i in 1:nrow(y)) 
{ 
    results <- NULL 
    for(j in 1:nrow(y)) 
    { 
    results <- c(results,sum((y[i,]==y[j,]),na.rm=TRUE)) 
    } 
    resultdf <- cbind(resultdf,results) 
} 
y <- cbind(y,resultdf) 

私はおそらく約7日間離れることを避けることができる反復計算をしています。

私が正しく理解していれば、より速いかもしれないいくつかの適用関数がCにあります。私は仕事をすることができませんでした。より速く動くパッケージがあれば私はまた興味があります。誰でも計算をスピードアップするのに役立つことができますか?

ありがとうございました!

+2

開始する前に 'y'を行列に変換するだけでどれくらいの速度が得られるのかを見て始めてください...' outer(y、y、== ==)の結果を並べ替えることで、 ")'適切に行と列の合計を取るが、私は今すぐそれを動作させる時間がありません... –

+0

...私は "繰り返し計算"あなたはすべての(i、j )よりも上三角だけではなく... –

+0

行列に変更すると、全部で約16分になります。そのヒントありがとう!そして、はい、それは三角形の1つを計算する代わりに計算を繰り返すことです。それについてどうやって行きますか?私はそれが下限を再計算するためにループの最後にi < - i + 1を追加していると推測していますが、決して行っていません。それを他の三角形にどのようにコピーしますか? – ARobertson

答えて

3

私はあなたの仕様に合わせてデータを作成し、マトリックスの使用に関するBenBolkerの提案@使用しています

> y <- matrix(sample(c(1:9, NA), 3200 * 1090, replace = TRUE), 
+    nrow = 3200, ncol = 1090) 

3つの異なる実装のための計算時間を比較した:

f1がで示唆されました@アンドレイ:

> f1 <- function(y)apply(y, 1, function(r1) 
+     apply(y, 1, function(r2)sum(r1==r2, na.rm=TRUE))) 

> system.time(r1 <- f1(y)) 
    user system elapsed 
523.51 0.77 528.73 

f2は@VincentZoonekyndによって示唆された:@BenBolkerによって示唆されるように

> f2 <- function(y) { 
+ f <- function(i,j) sum(y[i,] == y[j,], na.rm=TRUE) 
+ d <- outer(1:nrow(y), 1:nrow(y), Vectorize(f)) 
+ return(d) 
+ } 
> system.time(r2 <- f2(y)) 
    user system elapsed 
658.94 1.96 710.67 

f3は上三角上ダブルループです。それは、出力行列を事前に割り当てることで、それはまた、もう少し効率的にあなたのOPより:

> f3 <- function(y) { 
+ result <- matrix(NA, nrow(y), nrow(y)) 
+ for (i in 1:nrow(y)) { 
+  row1 <- y[i, ] 
+  for (j in i:nrow(y)) { 
+  row2 <- y[j, ] 
+  num.matches <- sum(row1 == row2, na.rm = TRUE) 
+  result[i, j] <- num.matches 
+  result[j, i] <- num.matches 
+  } 
+ } 
+ return(result) 
+ } 

> system.time(r3 <- f3(y)) 
    user system elapsed 
167.66 0.08 168.72 

ので、二重ループは、他の2つの答えのようにエレガントでコンパクトにしていないが、すべての3つの中で最速です。

+0

興味深いベンチマーク。通常、関数はループよりもはるかに高速に動作します。サプリー(ベクトル、楽しい)のように、しかしこのケースでは明らかにそうではありません。 – Andrei

+1

@Andrei、それは一般に真実ではありません。http://stackoverflow.com/questions/2275896/is-rs-apply-family-more-than-syntactic-sugarを参照してください。 – flodel

+0

リンクをありがとう。私は適用関数がより速いと信じていましたが、私は自分の考えを考え始めました。理由はわかりません:) – Andrei

2

実際には、apply関数を使用できます。行列が速く動作することを以前のヒントを考えると、私がしようとするだろう:

ym <- as.matrix(y) 
resultdf <- apply(ym, 1, function(r1) apply(ym, 1, function(r2) sum(r1==r2, na.rm=TRUE))) 
3

ここouterを使用して、別のソリューションです。

f <- function(i,j) sum(y[i,] == y[j,], na.rm=TRUE) 
d <- outer(1:nrow(y), 1:nrow(y), Vectorize(f)) 
1

あなたが(flodelの答え@からyf3を使用して)内部ループを取り除くことができます。

ty <- t(y) 
ix <- rep(1:nrow(y),each = ncol(y)) 
f4 <- function(y){ 
    result <- matrix(0L, nrow(y), nrow(y)) 
    for(r in 1:nrow(y)) 
     result[r,] <- rowsum(as.numeric(ty == y[r,]), ix, na.rm = T) 
    result 
} 



> system.time(out <- f4(y)) 
    user system elapsed 
52.616 21.061 74.000 
> system.time(out <- f3(y)) 
    user system elapsed 
244.751 0.136 244.954 
> 

それは実際には2回同じことを計算の余分な仕事をしていませんが、5倍の速さはまだあります。 rowsumの内部動作を使用することで、さらに4倍の速さにすることができます。例についてはquestionを参照してください。

+0

私はテストしましたが、計算時間は同じではありません。私のマシンでは、 'f4'は5倍*遅くなります。 ATLAS/MKL /などのような非標準ライブラリを使用しているか確認していますか? 'result [r、] flodel

+0

@flodel、すべて標準です、gnu linux R13.1 here。あなたの例のように大きな行列でテストしましたか?実際、小さな行列の場合、f4は遅くなります。 'rowsum'はスピードのために書かれており、多くのグループと多くのカラムでよく使用されます。 – VitoshKa

+0

私はOPで述べたように3200 x 1090のマトリックスでテストしました。 – flodel

関連する問題