Search code examples
rmultidimensional-arraysapply

How to perform an operation on a 3D array and a matrix whilst returning a 3D array?


In R, let's have an array and a matrix:

a <- array(rep(1:3, each = 4), dim = c(2, 2, 3))
b <- matrix(seq(0, 1, length.out = 6), nrow = 2, ncol = 3)

I want to use an function that utilises matrices from a along the 3rd dimension and columns in b as its two arguments. For this example, we can assume that my function is:

myfunc <- function(x, y) { x * y }

I want the operation to return a 3D array. My current solution is to use sapply for indices and transform the resulting list into an array subsequently:

res <- sapply(1:dim(a)[[3]], FUN = \(x) myfunc(a[, , x], b[, x]), simplify = FALSE) 
res <- abind::abind(res, along = 3)

Is there another way how to achieve this operation that would directly result in a 3D array? I experimented with sweep, but failed.


Solution

  • A possible approach is to change your 3D array and matrix into lists and use mapply. Here I wrote a simple function (to_list()) which does the array to list transformation (by default along the last array dimension).

    to_list <- function(x, along=length(dim(x))) {
      apply(x, along, identity, simplify=F)
    }
    
    res <- mapply(myfunc, to_list(b), to_list(a), SIMPLIFY=F)
    res <- sapply(res, identity, simplify='array')
    

    The sapply line does the same thing as your abind line.