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 matrices, 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.
CodePudding user response:
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.
CodePudding user response:
Similar to @Cettt's approach in tidyverse
- where we take in list
in pmap
, and then reduce
with %*%
. Note that the the 'columns' elements needs to be t
ransposed
library(purrr)
pmap(list(A, G, columns), ~ reduce(list(..1, ..2, t(..3)), `%*%`))
$a
[,1]
[1,] 333
[2,] 496
$b
[,1]
[1,] 486
[2,] 647
Or an option with Map
from base R
Map(\(x, y, z) Reduce(`%*%`, list(x, y, t(z))), A, G, columns)
$a
[,1]
[1,] 333
[2,] 496
$b
[,1]
[1,] 486
[2,] 647