有效地计算R中3d数组的行和

Rei*_*son 12 arrays r rowsum

考虑一下数组a:

> a <- array(c(1:9, 1:9), c(3,3,2))
> a
, , 1

     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9

, , 2

     [,1] [,2] [,3]
[1,]    1    4    7
[2,]    2    5    8
[3,]    3    6    9
Run Code Online (Sandbox Code Playgroud)

我们如何有效地计算由第三维索引的矩阵的行和,使得结果为:

     [,1] [,2]
[1,]   12   12
[2,]   15   15
[3,]   18   18
Run Code Online (Sandbox Code Playgroud)

??

通过以下'dims'参数可以轻松实现列总和colSums():

> colSums(a, dims = 1)
Run Code Online (Sandbox Code Playgroud)

但我不能找到一种方法,使用rowSums()阵列上,以达到预期的效果,因为它有一个不同的解读'dims'到的colSums().

使用以下方法计算所需的行总和很简单:

> apply(a, 3, rowSums)
     [,1] [,2]
[1,]   12   12
[2,]   15   15
[3,]   18   18
Run Code Online (Sandbox Code Playgroud)

但这只是隐藏循环.是否有其他有效的,真正的矢量化计算所需行总和的方法?

Rei*_*son 10

@ Fojtasek的回答提到拆分阵列让我想起了aperm()允许人们置换阵列尺寸的功能.作为colSums()工作,我们可以使用输出交换前两个维度aperm()colSums()在输出上运行.

> colSums(aperm(a, c(2,1,3)))
     [,1] [,2]
[1,]   12   12
[2,]   15   15
[3,]   18   18
Run Code Online (Sandbox Code Playgroud)

这个和其他的一些比较时间提出了基于R的答案:

> b <- array(c(1:250000, 1:250000),c(5000,5000,2))
> system.time(rs1 <- apply(b, 3, rowSums))
   user  system elapsed 
  1.831   0.394   2.232 
> system.time(rs2 <- rowSums3d(b))
   user  system elapsed 
  1.134   0.183   1.320 
> system.time(rs3 <- sapply(1:dim(b)[3], function(i) rowSums(b[,,i])))
   user  system elapsed 
  1.556   0.073   1.636
> system.time(rs4 <- colSums(aperm(b, c(2,1,3))))
   user  system elapsed 
  0.860   0.103   0.966 
Run Code Online (Sandbox Code Playgroud)

所以在我的系统上,aperm()解决方案显得更快:

> sessionInfo()
R version 2.12.1 Patched (2011-02-06 r54249)
Platform: x86_64-unknown-linux-gnu (64-bit)
Run Code Online (Sandbox Code Playgroud)

但是,rowSums3d()与其他解决方案没有给出相同的答案:

> all.equal(rs1, rs2)
[1] "Mean relative difference: 0.01999992"
> all.equal(rs1, rs3)
[1] TRUE
> all.equal(rs1, rs4)
[1] TRUE
Run Code Online (Sandbox Code Playgroud)


Foj*_*sek 6

您可以将数组切割成两个维度,计算其上的行总和,然后按照您希望的方式将输出重新组合在一起.像这样:

rowSums3d <- function(a){
    m <- matrix(a,ncol=ncol(a))
    rs <- rowSums(m)
    matrix(rs,ncol=2)
}

> a <- array(c(1:250000, 1:250000),c(5000,5000,2))
> system.time(rowSums3d(a))
   user  system elapsed 
   1.73    0.17    1.96 
> system.time(apply(a, 3, rowSums))
   user  system elapsed 
   3.09    0.46    3.74 
Run Code Online (Sandbox Code Playgroud)