2012-02-28 18 views
4

は、私は、このマトリックスにランダムに撮影した同じサイズのrowMeans 2の群間の差を取ることを望むスピードアップ行列rowMeans操作を

nc <- 5000 
nr <- 1024 
m <- matrix(rnorm(nc*nr), ncol=nc) 

、次の行列を考えてみましょう。

n <- 1000 # group size 

system.time(replicate(100, { 
    ind1 <- sample(seq.int(nc), n) 
    ind2 <- sample(seq.int(nc), n) 
    rowMeans(m[, ind1]) - rowMeans(m[, ind2]) 
})) 

それは、残念ながら、私はRprofの出力を理解していなかった(ほとんどの時間をis.data.frameに費やされたように見えた??)より効率的な何かのため

提案、非常に遅いのですか?

私は次のことを意図している:

  • Rcpp:私はそれはそれは、この段階で役立つだろうはっきりしていないので、RのrowMeansは、非常に効率的であると考えている私のオンライン測定値から。私はボトルネックが本当に最初であるかを確信したいと思っています。私のデザイン全体が最適ではないかもしれません。大部分の時間が小さな行列のそれぞれに対してコピーを作るのに費やされるならば、Rcppはより良い性能を発揮しますか?

  • R-develに更新すると、さらに効率的な新しい.rowMeans機能があるようです。誰もそれを試しましたか?

ありがとう。

+0

あなたがサンプリング、サブセット化し、すべてのアルマジロの違いをすれば、私はあなたが少しを得る疑うだろう。 RcppArmadillo経由で試すのに十分速いはずですか? –

+0

それはかなり簡単でしょうが、うまくいけば私は純粋なRで逃げることができます。また、Rcppで乱数を管理する経験はありません。 – baptiste

+0

Rcppの砂糖は、Rが使用する同じストリームを提供します:-) –

答えて

7

rowSums()コールはmと選択された列を示す0または1のベクトルと行列の乗算として見ることができます。あなたはすべてのそれらのベクトルを並べる場合は、(はるかに効率的である)二つの行列間の掛け算で終わる:

ind1 <- replicate(100, seq.int(nc) %in% sample(seq.int(nc), n)) 
ind2 <- replicate(100, seq.int(nc) %in% sample(seq.int(nc), n)) 
output <- m %*% (ind1 - ind2) 
+0

とても有望ですね、ありがとう!私は自分が正しいことをしていると確信する必要がありますが、確かに速くてエレガントです。 – baptiste

4

rowMeansを2回呼び出す必要はありません。最初に減算を行い、結果にrowMeansを呼び出すことができます。

x1 <- rowMeans(m[,ind1])-rowMeans(m[,ind2]) 
x2 <- rowMeans(m[,ind1]-m[,ind2]) 
all.equal(x1,x2) 
# [1] TRUE 

is.data.framerowMeansで行わチェックの一部です。

更新:については、内部コードのストレートコール(do_colsumは変更されていないと仮定)のようです。

.rowMeans <- function(X, m, n, na.rm = FALSE) 
    .Internal(rowMeans(X, m, n, na.rm)) 
あなたの場合

m=1024n=1000:それは次のように定義されています。 mからの列のサブセットに

+0

実際には、OPには '1に減らすことができる' rowMeans'に200回の呼び出し(2 * 100回の繰り返し)があるので、これはあなたが言うよりも優れています。 .. rm < - rowMeans(m); '(nc)、(nc)、n)]))' 'は0.1経過した秒をとります...(replicate(100、{rm [sample(seq.int(nc)、n) –

+0

@Joshua、2つの行列の差分をとることは、そのうちの1つのrowMeansを計算するのと同じくらい高価なものではないでしょうか?それは結局同じ数の操作です。 – flodel

+0

@BenBolker。また、 'rowMeans(m)'が 'replicate'呼び出しの外に保存できるという私の最初の推測でしたが、同じ問題を解決していません。 OPの出力は1024 x 10です。あなたと私が両方とも考えていたのは1000 x 10です。 – flodel