考虑数组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
我们如何有效地计算由第三维索引的矩阵的行和,以便得到结果:
[,1] [,2]
[1,] 12 12
[2,] 15 15
[3,] 18 18
...
通过'dims'
的{{1}}参数:
colSums()
但是我找不到在数组上使用> colSums(a, dims = 1)
来实现所需结果的方法,因为它对rowSums()
的解释与'dims'
的解释不同。
使用以下方法计算所需的行总和很简单:
colSums()
但这只是隐藏循环。是否有其他有效的,真正的矢量化计算所需行总和的方法?
答案 0 :(得分:10)
@ Fojtasek的回答提到拆分数组让我想起aperm()
函数,它允许人们置换数组的维度。当colSums()
有效时,我们可以使用aperm()
交换前两个维度,并在输出上运行colSums()
。
> colSums(aperm(a, c(2,1,3)))
[,1] [,2]
[1,] 12 12
[2,] 15 15
[3,] 18 18
这个和其他建议的基于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
因此,在我的系统上,aperm()
解决方案显得更快:
> sessionInfo()
R version 2.12.1 Patched (2011-02-06 r54249)
Platform: x86_64-unknown-linux-gnu (64-bit)
但是,rowSums3d()
没有给出与其他解决方案相同的答案:
> all.equal(rs1, rs2)
[1] "Mean relative difference: 0.01999992"
> all.equal(rs1, rs3)
[1] TRUE
> all.equal(rs1, rs4)
[1] TRUE
答案 1 :(得分: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
答案 2 :(得分:3)
我不知道最有效的方法,但sapply
似乎做得很好
a <- array(c(1:9, 1:9), c(3,3,2))
x1 <- sapply(1:dim(a)[3], function(i) rowSums(a[,,i]))
x1
[,1] [,2]
[1,] 12 12
[2,] 15 15
[3,] 18 18
x2 <- apply(a, 3, rowSums)
all.equal(x1, x2)
[1] TRUE
这提高了速度如下:
> a <- array(c(1:250000, 1:250000),c(5000,5000,2))
> summary(replicate(10, system.time(rowSums3d(a))[3]))
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.784 2.799 2.810 2.814 2.821 2.862
> summary(replicate(10, system.time(apply(a, 3, rowSums))[3]))
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.730 2.755 2.766 2.776 2.788 2.839
> summary(replicate(10, system.time( sapply(1:dim(a)[3], function(i) rowSums(a[,,i])) )[3]))
Min. 1st Qu. Median Mean 3rd Qu. Max.
1.840 1.852 1.867 1.872 1.893 1.914
计时完成了:
# Ubuntu 10.10
# Kernal Linux 2.6.35-27-generic
> sessionInfo()
R version 2.12.1 (2010-12-16)
Platform: x86_64-pc-linux-gnu (64-bit)
答案 3 :(得分:1)
如果您有一个多核系统,您可以编写一个简单的C函数并使用Open MP并行线程库。我已经为我的问题做了类似的事情,我在8核系统上获得了8倍的增长。代码仍然可以在单处理器系统上运行,甚至可以在没有OpenMP的系统上编译,也许在这里和那里有一些#ifdef _OPENMP。
当然,如果您知道大部分时间都在做什么,那么它唯一值得做的事情。在优化之前对代码进行概要分析。