Consider the array 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
How do we efficiently compute the row sums of the matrices indexed by the third dimension, such that the result is:
[,1] [,2]
[1,] 12 12
[2,] 15 15
[3,] 18 18
??
The column sums are easy via the 'dims'
argument of colSums()
:
> colSums(a, dims = 1)
but I cannot find a way to use rowSums()
on the array to achieve the desired result, as it has a different interpretation of 'dims'
to that of colSums()
.
It is simple to compute the desired row sums using:
> apply(a, 3, rowSums)
[,1] [,2]
[1,] 12 12
[2,] 15 15
[3,] 18 18
but that is just hiding the loop. Are there other efficient, truly vectorised, ways of computing the required row sums?
I don't know about the most efficient way of doing this, but
sapply
seems to do wellWhich gives a speed improvement as follows:
Timings were done on:
You could chop up the array into two dimensions, compute row sums on that, and then put the output back together the way you want it. Like so:
If you have a multi-core system you could write a simple C function and make use of the Open MP parallel threading library. I've done something similar for a problem of mine and I get an 8 fold increase on an 8 core system. The code will still work on a single-processor system and even compile on a system without OpenMP, perhaps with a smattering of #ifdef _OPENMP here and there.
Of course its only worth doing if you know that's what's taking most of the time. Do profile your code before optimising.
@Fojtasek's answer mentioned splitting up the array reminded me of the
aperm()
function which allows one to permute the dimensions of an array. AscolSums()
works, we can swap the first two dimensions usingaperm()
and runcolSums()
on the output.Some comparison timings of this and the other suggested R-based answers:
So on my system the
aperm()
solution appears marginally faster:However,
rowSums3d()
doesn't give the same answers as the other solutions: