Reputation: 19960
I know in R if I have a list of matrices, I can use the Reduce
function to apply an operation across all the matrices. For example:
l <- list(matrix(rnorm(16), 4, 4), matrix(rnorm(16), 4, 4))
Reduce(`*`, l)
But what if I want to apply this operation across multiple lists? I could do a brute-force approach with a for
loop but I feel like there should be a better way. I can do two lists with mapply
l2 <- l
mapply(`*`, l, l2, SIMPLIFY = FALSE)
But if I have more that two I'm not sure how to solve that.
The following thoughts all result in errors:
l3 <- l2
mapply(`*`, l, l2, l3, SIMPLIFY = FALSE)
Error in .Primitive("*")(dots[[1L]][[1L]], dots[[2L]][[1L]], dots[[3L]][[1L]]) :
operator needs one or two arguments
Reduce(`*`, list(l, l2, l3))
Error in f(init, x[[i]]) : non-numeric argument to binary operator
The desired output is a list of length 2 with the elementwise products of each matrix within each list. The brute-force loop would look like this:
out <- vector("list", length = 2)
for(i in 1:2){
out[[i]] <- l[[i]] * l2[[i]] * l3[[i]]
}
Upvotes: 2
Views: 87
Reputation: 38500
This combination of Reduce
and Map
will produce the desired result in base R.
# copy the matrix list
l3 <- l2 <- l
out2 <- Reduce(function(x, y) Map(`*`, x, y), list(l, l2, l3))
which returns
out2
[[1]]
[,1] [,2] [,3] [,4]
[1,] -5.614351e-01 -0.06809906 -0.16847839 0.8450600
[2,] -1.201886e-05 0.02008037 5.64656727 -2.4845526
[3,] 5.587296e-02 -0.54793853 0.02254552 0.4608697
[4,] -9.732049e-04 11.73020448 1.83408770 -1.4844601
[[2]]
[,1] [,2] [,3] [,4]
[1,] -4.7372339865 -0.398501528 0.8918474 0.12433983
[2,] 0.0007413892 0.151864126 -0.2138688 -0.10223482
[3,] -0.0790846342 -0.413330364 2.0640126 -0.01549591
[4,] -0.1888032661 -0.003773035 -0.9246891 -2.30731237
We can check that this is the same as the for
loop in the OP.
identical(out, out2)
[1] TRUE
Upvotes: 6