对角线之间有效的基质元素



i具有n*n矩阵形式的数据,我想为其进行一些计算(例如sum),其元素放在对角线之间(不包括对角线)。

例如,此矩阵:

     [,1] [,2] [,3] [,4] [,5]
[1,]    2    0    1    4    3
[2,]    5    3    6    0    4
[3,]    3    5    2    3    1
[4,]    2    1    5    3    2
[5,]    1    4    3    4    1

sum的结果(在对角线元素之间)是:

# left slice 5+3+2+5 = 15
# bottom slice 4+3+4+5 = 16
# right slice 4+1+2+3 = 10
# top slice 0+1+4+6 = 11
# dput(m)
m <- structure(c(2, 5, 3, 2, 1, 0, 3, 5, 1, 4, 1, 6, 2, 5, 3, 4, 0, 
3, 3, 4, 3, 4, 1, 2, 1), .Dim = c(5L, 5L))

如何有效地完成此操作?

这是您可以获得"顶部切片"的方法:

sum(m[lower.tri(m)[nrow(m):1,] & upper.tri(m)])
#[1] 11

可视化它:

lower.tri(m)[nrow(m):1,] & upper.tri(m)
#      [,1]  [,2]  [,3]  [,4]  [,5]
#[1,] FALSE  TRUE  TRUE  TRUE FALSE
#[2,] FALSE FALSE  TRUE FALSE FALSE
#[3,] FALSE FALSE FALSE FALSE FALSE
#[4,] FALSE FALSE FALSE FALSE FALSE
#[5,] FALSE FALSE FALSE FALSE FALSE

这是您可以计算所有4个切片的方法:

up <- upper.tri(m)
lo <- lower.tri(m)
n <- nrow(m)
# top
sum(m[lo[n:1,] & up])
# left
sum(m[lo[n:1,] & lo])
# right
sum(m[up[n:1,] & up])
# bottom
sum(m[up[n:1,] & lo])
sum(sapply(1:dim(m)[[2L]], function(i) sum(m[c(-i,-(dim(m)[[1L]]-i+1)),i])))

此列列列为列,并且每个列都取出对角线元素并总和其余的元素。然后将这些部分结果求和。

我相信这会很快,因为我们按列进行列,而r中的矩阵则由列存储(即,它将是CPU CACHE INGRALENT友好型)。我们也不必生成大量的索引,只有两个索引的向量(将其取出)。

编辑:我再次仔细阅读了这个问题。可以更新该代码以在sapply中为每个元素的每个元素生成四个值:对于每个区域。这个想法保持不变,对于大型矩阵,如果您逐列进行,则不会在列之间来回跳动。

最新更新