我需要计算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)
答案 0 :(得分: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
这会为您提供与原始订单相同的结果。
答案 1 :(得分: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