2017-09-26 1 views
1
私は思っていた

、たくさんあります。例えば、いくつかの行列を変換したい、とあなたはループのために使用機能がインデックスに依存する場合)(適用し、変異する()効率

Y[i,j] = i*j*X[i,j] 

ような何かをしたいと仮定apply()は、それが使用しているiとjを知らない。

私が考えることができる解決策は、列i、j、Xを持つdata.frame-likeオブジェクトを定義し、mutate()を使用して目的のY値を取得することです。

私は2つの質問がある:

(a)のではなく、forループの)適用使用上の行列を(構築することは可能ですか?もしそうなら、それをこのように構築するか、mutate()を使って効率を上げるのですか?

(b)matrixとdata.frameの両方のオブジェクト表現があるとします。行と列のインデックスを含む操作を実行すると効率的ですか?たとえば、(Y [i、j] - 平均(Y))2 /(i * j)の合計のような統計が必要な場合。私は行とcolのインデックスで行列を構築し、ベクトル化された関数を使うことができるのは分かっていますが、mutateを使うよりも優れていますか?

答えて

4

あなたの行列がどのように大規模でスパースに応じて、あなたは試してみることがまず最初に、それぞれrowcolumnインデックスを構築するためにrowcol機能を使用して、あなたの行列を変換するためにそれを使用している:

X <- matrix(1:9, 3, 3) 

row(X) * col(X) * X 
#  [,1] [,2] [,3] 
#[1,] 1 8 21 
#[2,] 4 20 48 
#[3,] 9 36 81 

はその後(Y[i,j] - mean(Y))²/(i*j)のために、それは同様だ:

Y <- row(X) * col(X) * X 
(Y - mean(Y))^2/(row(Y) * col(Y)) 

#   [,1]  [,2]  [,3] 
#[1,] 592.11111 150.222222 6.259259 
#[2,] 227.55556 7.111111 85.629630 
#[3,] 88.92593 18.962963 344.308642 

これは、完全にベクトル化されたアプローチであり、applyまたはfor loopは不要ですが、追加のメモリが必要です。

2

私はouterが速いかもしれないと思いますrow(X) * col(X)

# Define dimensions 
n.rows <- n.cols <- 1000 

# Define matrix 
X <- matrix(runif(n.rows * n.cols), ncol = n.cols) 

# Psidom's approach 
rowcol.method <- function(X){row(X) * col(X) * X} 

# Approach using outer 
outer.method <- function(X){outer(1:nrow(X), 1:ncol(X)) * X} 

# Benchmark library 
library(microbenchmark) 

# Test 
microbenchmark(
    rowcol.method(X), 
    outer.method(X) 
) 

結果:

Unit: milliseconds 
      expr  min  lq  mean median  uq  max neval cld 
rowcol.method(X) 20.895870 21.154815 23.795695 21.612485 22.584323 62.50660 100 b 
    outer.method(X) 5.608577 5.729724 6.883643 5.836526 5.977156 50.12508 100 a 

比較出力:他の計算のための同様

identical(rowcol.method(X), outer.method(X)) 
[1] TRUE 

、外側アプローチの狂っ外れ値があったが( 221.66718ミリ秒)。

# Define matrix 
Y <- row(X) * col(X) * X 

# Psidom's approach 
rowcol.method.Y <- function(Y) {(Y - mean(Y))^2/(row(Y) * col(Y))} 

# Approach using outer 
outer.method.Y <- function(Y) {(Y - mean(Y))^2/outer(1:nrow(X), 1:ncol(X))} 

# Test 
microbenchmark(
    rowcol.method.Y(Y), 
    outer.method.Y(Y) 
) 

結果:

Unit: milliseconds 
       expr  min  lq  mean median  uq  max neval cld 
rowcol.method.Y(Y) 27.94405 30.18635 34.63551 33.32627 37.06467 46.58983 100 b 
    outer.method.Y(Y) 11.27064 12.66349 18.77192 15.66756 18.18864 221.66718 100 a 

比較出力:

identical(rowcol.method.Y(Y), outer.method.Y(Y)) 
[1] TRUE 
関連する問題