16

私は行列を持っており、それをn回複製する効率的な方法を探しています(nはデータセット内の観測値の数です)。たとえば、行列Aがある場合

A <- matrix(1:15, nrow=3)

次に、フォームの出力が必要です

rbind(A, A, A, ...) #n times

for明らかに、たとえばループapplyや同様の関数を使用して、このような大きな行列を作成する方法はたくさんあります。ただし、「matrix-replication-function」の呼び出しは、最適化アルゴリズムのコアで行われ、プログラムの1回の実行中に何万回も呼び出されます。したがって、ループ、apply-typeタイプの関数、およびそれに類似したものは十分に効率的ではありません。(このような解決策は、基本的にnのループが数万回実行されることを意味しますが、これは明らかに非効率的です。)私はすでに通常の関数を使用しようとしましたが、の出力を行列repに配置する方法が見つかりませんでした。rep希望のフォーマットの。

この場合、頻繁に使用されるため、このソリューション do.call("rbind", replicate(n, A, simplify=F)) は非効率的です。rbind(その後、私のプログラムの総実行時間の約30%がrbindsの実行に費やされます。)

誰かがより良い解決策を知っていますか?

4

6 に答える 6

25

さらに 2 つの解決策:

1つ目は、質問の例の修正です

do.call("rbind", rep(list(A), n))

2 つ目は、行列の展開、複製、再構築です。

matrix(rep(t(A),n), ncol=ncol(A), byrow=TRUE)

効率性が求められているため、ベンチマークが必要

library("rbenchmark")
A <- matrix(1:15, nrow=3)
n <- 10

benchmark(rbind(A, A, A, A, A, A, A, A, A, A),
          do.call("rbind", replicate(n, A, simplify=FALSE)),
          do.call("rbind", rep(list(A), n)),
          apply(A, 2, rep, n),
          matrix(rep(t(A),n), ncol=ncol(A), byrow=TRUE),
          order="relative", replications=100000)

与える:

                                                 test replications elapsed
1                 rbind(A, A, A, A, A, A, A, A, A, A)       100000    0.91
3                   do.call("rbind", rep(list(A), n))       100000    1.42
5  matrix(rep(t(A), n), ncol = ncol(A), byrow = TRUE)       100000    2.20
2 do.call("rbind", replicate(n, A, simplify = FALSE))       100000    3.03
4                                 apply(A, 2, rep, n)       100000    7.75
  relative user.self sys.self user.child sys.child
1    1.000      0.91        0         NA        NA
3    1.560      1.42        0         NA        NA
5    2.418      2.19        0         NA        NA
2    3.330      3.03        0         NA        NA
4    8.516      7.73        0         NA        NA

したがって、最速は生の呼び出しですが、それは固定されており、事前にわかってrbindいることを前提としています。nが固定されていない場合n、最速はdo.call("rbind", rep(list(A), n)です。これらは、3x5 マトリックスと 10 回の複製用でした。行列のサイズが異なると、順序が異なる場合があります。

編集:

n=600 の場合、結果は異なる順序になります (明示的なrbindバージョンは除外されます)。

A <- matrix(1:15, nrow=3)
n <- 600

benchmark(do.call("rbind", replicate(n, A, simplify=FALSE)),
          do.call("rbind", rep(list(A), n)),
          apply(A, 2, rep, n),
          matrix(rep(t(A),n), ncol=ncol(A), byrow=TRUE),
          order="relative", replications=10000)

与える

                                                 test replications elapsed
4  matrix(rep(t(A), n), ncol = ncol(A), byrow = TRUE)        10000    1.74
3                                 apply(A, 2, rep, n)        10000    2.57
2                   do.call("rbind", rep(list(A), n))        10000    2.79
1 do.call("rbind", replicate(n, A, simplify = FALSE))        10000    6.68
  relative user.self sys.self user.child sys.child
4    1.000      1.75        0         NA        NA
3    1.477      2.54        0         NA        NA
2    1.603      2.79        0         NA        NA
1    3.839      6.65        0         NA        NA

明示的なrbindバージョンを含めると、バージョンよりわずかに速くなりますがdo.call("rbind", rep(list(A), n))、大幅には変わらず、applyまたはmatrixバージョンよりも遅くなります。したがって、この場合、任意への一般化nは速度の低下を必要としません。

于 2012-10-23T16:53:40.923 に答える
10

おそらくこれはより効率的です:

apply(A, 2, rep, n)
于 2012-10-23T16:19:07.417 に答える
3

こんな方法もあります:

rep(1, n) %x% A
于 2015-08-01T22:37:18.403 に答える
0

それを配列に変換し、コンテンツを複製し、更新された行数で新しいマトリックスを作成するのはどうですか?

A <- matrix(...)
n = 2 # just a test

a = as.integer(A)
multi.a = rep(a,n)
multi.A = matrix(multi.a,nrow=nrow(A)*n,byrow=T)
于 2012-10-23T16:23:32.690 に答える