47

私は行列mとベクトルを持っていvます。行列mの最初の列を vector の最初の要素でv乗算し、行列の 2 番目の列をmvector の 2 番目の要素で乗算vします。次のコードでそれを行うことができますが、2 つの転置呼び出しを必要としない方法を探しています。Rでこれをより速く行うにはどうすればよいですか?

m <- matrix(rnorm(120000), ncol=6)
v <- c(1.5, 3.5, 4.5, 5.5, 6.5, 7.5)

system.time(t(t(m) * v))

#   user  system elapsed 
#   0.02    0.00    0.02 
4

6 に答える 6

26

列の数が多い場合、 t(t(m) * v) ソリューションは行列乗算ソリューションよりも大幅に優れています。ただし、より高速なソリューションがありますが、メモリ使用量が高くなります。rep() を使用して m の大きさの行列を作成し、要素ごとに乗算します。mnelの例を変更した比較は次のとおりです。

m = matrix(rnorm(1200000), ncol=600)
v = rep(c(1.5, 3.5, 4.5, 5.5, 6.5, 7.5), length = ncol(m))
library(microbenchmark)

microbenchmark(t(t(m) * v), 
  m %*% diag(v),
  m * rep(v, rep.int(nrow(m),length(v))), 
  m * rep(v, rep(nrow(m),length(v))), 
  m * rep(v, each = nrow(m)))

# Unit: milliseconds
#                                   expr        min         lq       mean     median         uq       max neval
#                            t(t(m) * v)  17.682257  18.807218  20.574513  19.239350  19.818331  62.63947   100
#                          m %*% diag(v) 415.573110 417.835574 421.226179 419.061019 420.601778 465.43276   100
#  m * rep(v, rep.int(nrow(m), ncol(m)))   2.597411   2.794915   5.947318   3.276216   3.873842  48.95579   100
#      m * rep(v, rep(nrow(m), ncol(m)))   2.601701   2.785839   3.707153   2.918994   3.855361  47.48697   100
#             m * rep(v, each = nrow(m))  21.766636  21.901935  23.791504  22.351227  23.049006  66.68491   100

ご覧のとおり、rep() で「each」を使用すると、速度が犠牲になり、わかりやすくなります。rep.int と rep の違いはごくわずかのようです。どちらの実装も、microbenchmark() を繰り返し実行すると場所が入れ替わります。ncol(m) == length(v) であることに注意してください。

自動プロット

于 2015-09-02T22:44:44.890 に答える
3

@Arun が指摘しているように、時間効率の点であなたのソリューションを上回るかどうかはわかりません。ただし、コードの理解度に関しては、他のオプションがあります。

1 つのオプション:

> mapply("*",as.data.frame(m),v)
      V1  V2  V3
[1,] 0.0 0.0 0.0
[2,] 1.5 0.0 0.0
[3,] 1.5 3.5 0.0
[4,] 1.5 3.5 4.5

そしてもう一つ:

sapply(1:ncol(m),function(x) m[,x] * v[x] )
于 2013-06-13T06:02:30.107 に答える
1

bluegrue で行われているように、単純な rep で要素ごとの乗算を実行することもできます。

乗算と加算の回数は、単純な行列乗算が実行されるかのように大幅に削減されますdiag()。この場合、多くのゼロ乗算を回避できます。

m = matrix(rnorm(1200000), ncol=6)
v=c(1.5, 3.5, 4.5, 5.5, 6.5, 7.5)
v2 <- rep(v,each=dim(m)[1])
library(microbenchmark)
microbenchmark(m %*% diag(v), t(t(m) * v), m*v2)

Unit: milliseconds
          expr       min        lq      mean    median        uq      max neval cld
 m %*% diag(v) 11.269890 13.073995 16.424366 16.470435 17.700803 95.78635   100   b
   t(t(m) * v)  9.794000 11.226271 14.018568 12.995839 15.010730 88.90111   100   b
        m * v2  2.322188  2.559024  3.777874  3.011185  3.410848 67.26368   100  a 
于 2017-03-05T14:17:04.280 に答える