2012-05-01 38 views
19

expand.gridはできるだけ速く探しています。私はベクトルを作成するために過去に同様の目的のためにouterを使用しました。このような何か:expand.gridの代わりにouterを使用

v <- outer(letters, LETTERS, paste0) 
unlist(v[lower.tri(v)]) 

ベンチマークはouterexpand.gridより大幅に高速になりますことを私に示しているが、私はちょうどexpand.gridのように2つの列を作成したい、この時間(2つのベクトルのすべての可能なコンボ)が、outerと私の方法はありません今回はアウターとのベンチマークが速かった。

私は2つのベクトルを取り、できるだけ速く(私はouterルートかもしれないと思うが、任意の基本メソッドに大きく開いています二つの列など、すべての可能なコンボを作成するために願っています。

ここexpand.grid方法だとouter方法

dat <- cbind(mtcars, mtcars, mtcars) 

expand.grid(seq_len(nrow(dat)), seq_len(ncol(dat))) 

FOO <- function(x, y) paste(x, y, sep=":") 
x <- outer(seq_len(nrow(dat)), seq_len(ncol(dat)), FOO) 
apply(do.call("rbind", strsplit(x, ":")), 2, as.integer) 

microbenchmarkingがouterが遅い示しています。

#  expr  min  lq median  uq  max 
# EXPAND.G 812.743 838.6375 894.6245 927.7505 27029.54 
# OUTER 5107.871 5198.3835 5329.4860 5605.2215 27559.08 

outer私はouterを使って、長さ2のベクトルを直接作成する方法がわからないので、私はdo.call('rbind'を一緒に使うことができると思っています。私はpasteと遅い分割を遅らせる必要があります。私はouter(またはbaseの他の方法)を使って、expand gridよりも速い方法でこれをどうやって行うことができますか?

編集: マイクロベンチマーク結果の追加。

**

Unit: microseconds 
     expr  min  lq median  uq  max 
1 ERNEST 34.993 39.1920 52.255 57.854 29170.705 
2  JOHN 13.997 16.3300 19.130 23.329 266.872 
3 ORIGINAL 352.720 372.7815 392.377 418.738 36519.952 
4 TOMMY 16.330 19.5960 23.795 27.061 6217.374 
5 VINCENT 377.447 400.3090 418.505 451.864 43567.334 

**

enter image description here

+0

タイラー、私の方法をベンチマークリストに追加してもよろしいですか?あなたがここで持っている中で最も速いスピードのスピードの半分になるはずです。 – John

+0

はい。それは確かに最も速いです。 –

答えて

12

expand.grid.alt <- function(seq1,seq2) { 
    cbind(rep.int(seq1, length(seq2)), 
     c(t(matrix(rep.int(seq2, length(seq1)), nrow=length(seq2))))) 
} 

expand.grid.alt(seq_len(nrow(dat)), seq_len(ncol(dat))) 

私のコンピュータでは、より高速なexpand.gridよりも6倍のようなものです。

+0

私は非常に懐疑的でしたが、それは非常に速いです。いい返答。私は外側が私が取っていたはずのアプローチではなかったと思う。上記のWIn 7マシンでマイクロベンチマーキング結果を掲載しました。 –

+1

@TylerRinker注意してください、私の機能にバグがありました! 'nrow'引数は間違っていました。私は今それを修正しました。 –

+0

@ErnestA最後のコード行の右端にかっこを追加してから、編集を送信する前にもう少しテキストを追加する必要がありました。 –

3

あなたは別に2つの列を作成することができます。 rep.intを使用して

library(microbenchmark) 
n <- nrow(dat) 
m <- ncol(dat) 
f1 <- function() expand.grid(1:n, 1:m) 
f2 <- function() 
    data.frame( 
    Var1 = as.vector(outer(1:n, rep(1,m))), 
    Var2 = as.vector(outer(rep(1,n), 1:m)) 
) 
microbenchmark(f1, f2, times=1e6) 
# Unit: nanoseconds 
# expr min lq median uq max 
# 1 f1 70 489 490 559 168458 
# 2 f2 70 489 490 559 168597 
+0

お返事ありがとうございます。あなたは私の外側の問題を解決し、学習はすばらしかったです。アーネストのアプローチは非常に迅速で、外部アプローチよりもはるかに高速です。 –

4

@ErnestAには、非常に優れた解決策があります。

...それはしかしわずかに速くなることができます

expand.grid.alt2 <- function(seq1,seq2) { 
    cbind(Var1=rep.int(seq1, length(seq2)), Var2=rep(seq2, each=length(seq1))) 
} 

s1=seq_len(2000); s2=seq_len(2000) 
system.time(for(i in 1:10) expand.grid.alt2(s1, s2)) # 1.58 
system.time(for(i in 1:10) expand.grid.alt(s1, s2)) # 1.75 
system.time(for(i in 1:10) expand.grid(s1, s2))  # 2.46 
+0

アーネストのスピードは間違いなく素晴らしいです。 +1アーネストのチェックを続けるつもりですが、私はすでにチェックをしているので、これは速いです。私は再割り当てについて面白いと感じます。彼の答えに基づいていれば、私は完全に安らかに感じるでしょう:)あなたがしたかどうか聞いてもよろしいですか? –

+1

@TylerRinker - そうでした。だからあなたは今、完全に安易に感じることができます;-) – Tommy

+0

@トミー私はそれがより遅くなると思ったので、 'rep(... each =)'を避けるために偉大な長さに行きました。実際、そうではありません。 –

13

rep.intのドキュメントはかなり完全なものではありません。 repの場合のように、times引数のベクトルを渡すことができるので、最も一般的なケースでは単なる最速ではありません。両方のシーケンスで簡単に使用することで、Tommyの40%程度の時間を短縮できます。

expand.grid.jc <- function(seq1,seq2) { 
    cbind(Var1 = rep.int(seq1, length(seq2)), 
    Var2 = rep.int(seq2, rep.int(length(seq1),length(seq2)))) 
} 
+0

現在の状態でコードがエラーをスローします。私はどこかで括弧が欠けていると思うが、どこを見つけることができなかった。 –

+0

+1恐ろしい!明らかに、 'rep'は' each'引数をどのように扱うかを改善する必要があります... – Tommy

+0

はいTommy、それは...私は実際にそう考えるべきですexpand.gridは、私が内部的に書いたようなものを使用しています...エラーチェックとロバスト性のために遅いです。 – John

関連する問題