Search code examples
rarraysapplydimensions

How use apply for each matrix in 3-d array in R


If you have a function f that takes a matrix and returns a matrix with different dimensions. Is there a way to use R's apply with f for each matrix in an 3-d array and return an array with altered dimension.

For instance, say I have

f <- function(m)(m[,1:2] + m[,3:4]) / rowSums(m)

and the array

A <- array(1:40, dim = c(2,5,4))

Then if I interpret the dimension as index for the (2) matrices, I get on the first matrix:

> f1(A[1,,])
          [,1]      [,2]
[1,] 0.3437500 0.6562500
[2,] 0.3611111 0.6388889
[3,] 0.3750000 0.6250000
[4,] 0.3863636 0.6136364
[5,] 0.3958333 0.6041667

That is a c(5,2) matrix. In my head I keep thinking apply as "do this function for each margin slice", and believe I can do:

> apply(A, 1, f1)
           [,1]      [,2]
 [1,] 0.3437500 0.3529412
 [2,] 0.3611111 0.3684211
 [3,] 0.3750000 0.3809524
 [4,] 0.3863636 0.3913043
 [5,] 0.3958333 0.4000000
 [6,] 0.6562500 0.6470588
 [7,] 0.6388889 0.6315789
 [8,] 0.6250000 0.6190476
 [9,] 0.6136364 0.6086957
[10,] 0.6041667 0.6000000

This is the results rbind'ed/stacked with dim c(10,2) where I wanted them as an c(2,5,2) array.


Solution

  • If we don't want to simplify, an option is

    apply(A, 1, function(x) list(f1(x)))
    

    Or convert to array

    array(apply(A, 1, f1), dim = c(2, 5, 2))
    

    Based on the results with f1(A[1,,]), the output can be

    array(apply(A, 1, f1), dim = c(5, 2, 2))