2012-12-17 5 views
10

n×n行列の各非対角要素の平均を計算する必要があります。下三角と上三角は冗長です。現在使用しているコードは次のとおりです。大きな行列の非対角平均を高速に計算する

A <- replicate(500, rnorm(500)) 
sapply(1:(nrow(A)-1), function(x) mean(A[row(A) == (col(A) - x)])) 

これは動作しているようですが、大きな行列ではうまく調整できません。私が持っているものは、2から5000^2の周りに、巨大ではありませんが、それでも1000^2は、私が好きよりも時間がかかっています:

A <- replicate(1000, rnorm(1000)) 
system.time(sapply(1:(nrow(A)-1), function(x) mean(A[row(A) == (col(A) - x)]))) 
> user system elapsed 
> 26.662 4.846 31.494 

これを行うには、よりスマートな方法はありますか?

編集明確にするために、私は各対角線の平均を独立して、以下のために:

1 2 3 4 
1 2 3 4 
1 2 3 4 
1 2 3 4 

私が希望:

mean(c(1,2,3)) 
mean(c(1,2)) 
mean(1) 

答えて

14

あなただけのリニアアドレッシングを使用して直接対角線を抽出することにより、大幅に高速取得することができます:ここsuperdiagはAからi番目の対角を抽出する(I = 1は、主要な対角です)

> A <- replicate(1000, rnorm(1000)) 

> system.time(sapply(1:(nrow(A)-1), function(x) mean(A[row(A) == (col(A) - x)]))) 
    user system elapsed 
26.464 3.345 29.793 

> system.time(superdiagmeans(A)) 
    user system elapsed 
    0.033 0.006 0.039 

これはあなたに結果を与える:1K正方行列でこれを実行する

superdiag <- function(A,i) { 
    n<-nrow(A); 
    len<-n-i+1; 
    r <- 1:len; 
    c <- i:n; 
    indices<-(c-1)*n+r; 
    A[indices] 
} 

superdiagmeans <- function(A) { 
    sapply(2:nrow(A), function(i){mean(superdiag(A,i))}) 
} 

〜の800倍の高速化を提供しますオリジナルと同じ順番で表示されます。

+1

インデックスの良い使用。私は受け入れられた答えとしてこの1つに投票します。これは、どのように強力な指標ができるかを示しています。 –

+1

ありがとうございますが、あなたの方がはっきりしています。@ JorisMeys;このアプローチは、_lot_と2番目の広告の10分の1を行う必要がある場合にのみ、余分な合併症の価値があります。 –

+0

それは非常にスマートです - 何が起こっていたのかを理解するためにインデックス世代を作業しなければなりませんでした。答えが – blmoore

10

をあなたは次の関数を使用することができます。

diagmean <- function(x){ 
    id <- row(x) - col(x) 
    sol <- tapply(x,id,mean) 
    sol[names(sol)!='0'] 
} 

私たちはあなたの行列でこれを確認した場合、速度ゲインはかなりのものである:

> system.time(diagmean(A)) 
    user system elapsed 
    2.58 0.00 2.58 

> system.time(sapply(1:(nrow(A)-1), function(x) mean(A[row(A) == (col(A) - x)]))) 
    user system elapsed 
    38.93 4.01 42.98 

この関数は、上三角形と下三角形の両方を計算します。

diagmean <- function(A){ 
    id <- row(A) - col(A) 
    id[id>=0] <- NA 
    tapply(A,id,mean) 
} 

このようにすると、次のような結果が得られます。解決策は、あなたに比べて逆転されることに注意してください:

> A <- matrix(rep(c(1,2,3,4),4),ncol=4) 

> sapply(1:(nrow(A)-1), function(x) mean(A[row(A) == (col(A) - x)])) 
[1] 2.0 1.5 1.0 

> diagmean(A) 
-3 -2 -1 
1.0 1.5 2.0 
+0

優れた、1k^2マトリックスのマシンでは1秒未満です。ありがとうございました – blmoore

関連する問題