Search code examples
rlistmatrixpurrrmultiplication

use map2 to multiply more than two lists of matrices in R


I have

A = list(a = matrix(1:4, 2), b = matrix(2:5, 2))

G = list(a = matrix(10:13, 2), b = matrix(25:28, 2))

columns <- list(a = matrix(3:4, 1), b = matrix(1:2, 1))

I want to make another list of cross-products of all the elements with the same name across lists, so I do purrr::map2(A, G, columns, `%*%`). It doesn't look like map2 allows more than two elements. Is there a workaround?

Error in `stop_bad_length()`:
! Index 1 must have length 1, not 2
Backtrace:
 1. purrr::map2(A, G, columns, `%*%`)
 4. purrr:::stop_bad_element_length(...)
 5. purrr:::stop_bad_length(...)

I also tried purrr::pmap(list(A, G, columns), %*%), but no luck.

purrr::map2(A, G, `%*%`) works beautifully.


Solution

  • The problem is that the function you are trying to apply ('%*%') is a function which only takes two arguments and not three.

    For your problem I would recommend Reduce (or purrr::reduce): in this case Reduce starts with two matrices and multiplies them. Then it multiplies the result with the third matrix. Theoretically you could go on like this.

    lapply(seq_along(A), \(k) Reduce('%*%', list(A[[k]],G[[k]], t(columns[[k]]))))
    
    [[1]]
         [,1]
    [1,]  333
    [2,]  496
    
    [[2]]
         [,1]
    [1,]  486
    [2,]  647
    

    Note that I had to transpose the matrices inside column because they do not have the right size.