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)
4

2 に答える 2

14

線形アドレッシングを使用して対角線を直接抽出するだけで、大幅に高速化できます。superdiagここでは、A から i 番目の上対角線を抽出します (i=1 は主対角線です)。

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))})
}

これを 1K 正方行列で実行すると、最大 800 倍のスピードアップが得られます。

> 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 

これにより、元の順序と同じ順序で結果が得られます。

于 2012-12-17T14:02:40.480 に答える
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 
于 2012-12-17T13:44:29.990 に答える