22

私は可能な限りスピードを求めており、基地にとどまって何をすべきかを考えてexpand.gridいます。outer過去に同様の目的でベクトルを作成するために使用しました。このようなもの:

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

ベンチマークでは、これouterよりも大幅に高速になる可能性があることが示されましたが、今回は 2 つの列(2 つのベクトルに対して可能なすべての組み合わせ)expand.gridと同じように作成したいと考えていますが、私の方法では今回はアウターほど高速ではありません。expand.gridouter

私は2つのベクトルを取り、可能な限りすべてのコンボを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)

マイクロベンチマーク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

一緒にできる長さ2のベクトルを直接作成するouter方法がわからないため、使用が遅いと思います。私はゆっくりとゆっくりと分割する必要があります。よりも高速な方法で (または の他のメソッド) でこれを行うにはどうすればよいですか?outerdo.call('rbind'pasteouterbaseexpand 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

**

ここに画像の説明を入力

4

4 に答える 4

17

のドキュメントrep.intは完全ではありません。のように times 引数にベクトルを渡すことができるため、最も一般的なケースで最速というだけではありませんrep。両方のシーケンスに簡単に使用でき、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))))
}
于 2012-05-02T03:49:05.077 に答える
16

使用rep.int:

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)))

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

于 2012-05-02T00:01:25.640 に答える
5

@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
于 2012-05-02T01:33:23.393 に答える
3

2つの列を別々に作成できます。

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
于 2012-05-01T23:34:58.970 に答える