useryk
useryk

Reputation: 309

Matrix multiplication over three lists of matrices using apply() in R?

I am trying to do matrix multiplication over three lists of matrices, using apply() or something alike.

Here are the sample data:

mat1 <- matrix(c(1:16), 4, 4, byrow = TRUE)
mat2 <- matrix(c(1:16), 4, 4, byrow = TRUE)
mat3 <- matrix(c(1:16), 4, 4, byrow = TRUE)

l1 <- list(mat1, mat2, mat3)
l2 <- list(mat1, mat2, mat3)
l3 <- list(mat1, mat2, mat3)

I'd like to do the following and dump them into a new list, for each corresponding [[n]] in all three lists:

l1[[1]] %*% l2[[1]] %*% l3[[1]]
l1[[2]] %*% l2[[2]] %*% l3[[2]]
l1[[3]] %*% l2[[3]] %*% l3[[3]]

I tried the following:

mat <- lapply(c(mat1, mat2, mat3), function(x) x[1] %*% x[2] %*% x[3])

But I am not getting what I need. Please help?

Upvotes: 4

Views: 688

Answers (3)

Zheyuan Li
Zheyuan Li

Reputation: 73265

I suggest using the following:

mat1 <- matrix(c(1:16), 4, 4, byrow = TRUE)
mat2 <- matrix(c(1:16), 4, 4, byrow = TRUE)
mat3 <- matrix(c(1:16), 4, 4, byrow = TRUE)

l1 <- list(mat1, mat2, mat3)
l2 <- list(mat1, mat2, mat3)
l3 <- list(mat1, mat2, mat3)

f <- function (...) Reduce("%*%", list(...))
mapply(f, l1, l2, l3, SIMPLIFY = FALSE) 

#[[1]]
#      [,1]  [,2]  [,3]  [,4]
#[1,]  3140  3560  3980  4400
#[2,]  7268  8232  9196 10160
#[3,] 11396 12904 14412 15920
#[4,] 15524 17576 19628 21680
#
#[[2]]
#      [,1]  [,2]  [,3]  [,4]
#[1,]  3140  3560  3980  4400
#[2,]  7268  8232  9196 10160
#[3,] 11396 12904 14412 15920
#[4,] 15524 17576 19628 21680
#
#[[3]]
#      [,1]  [,2]  [,3]  [,4]
#[1,]  3140  3560  3980  4400
#[2,]  7268  8232  9196 10160
#[3,] 11396 12904 14412 15920
#[4,] 15524 17576 19628 21680

The good point is that it does not matter how many lists you feed to mapply. For example,

mapply(f, l1, l2, l3, l1, l3, l3, SIMPLIFY = FALSE)

works, too. That is the magic power of Reduce and ....

Upvotes: 5

IRTFM
IRTFM

Reputation: 263332

It appears you want element-wise multiplication. That is accomplished with the *-operator. If these were in a list (avoiding the c() operation which created one big vector and loss all dimensions) then you can use Reduce:

> l1 <- list( mat1, mat2, mat3)
> 
> Reduce("*", l1)
     [,1] [,2] [,3] [,4]
[1,]    1    8   27   64
[2,]  125  216  343  512
[3,]  729 1000 1331 1728
[4,] 2197 2744 3375 4096

If you wnated iot as a vector you could then use c:

 c( Reduce("*", l1) )
 [1]    1  125  729 2197    8  216 1000 2744   27  343 1331 3375   64  512 1728
[16] 4096

If as suggested you wanted matrix multiplication, then perhaps this (with my list of your matrices):

 c( Reduce("%*%", l1) )

 [1]  3140  7268 11396 15524  3560  8232 12904 17576  3980  9196 14412 19628  4400
 [14] 10160 15920 21680

Upvotes: 1

Stephen
Stephen

Reputation: 324

Here is what you want in terms of matrix multiplication

mat1 <- as.list(matrix(c(1:16), 4, 4, byrow = TRUE))
mat2 <- as.list(matrix(c(1:16), 4, 4, byrow = TRUE))
mat3 <- as.list(matrix(c(1:16), 4, 4, byrow = TRUE))

l1 <- list(mat1, mat2, mat3)
l2 <- list(mat1, mat2, mat3)
l3 <- list(mat1, mat2, mat3)

matrix(unlist(l1[[1]]),4,4) %*% matrix(unlist(l2[[1]]),4,4) %*% matrix(unlist(l3[[1]]),4,4)
matrix(unlist(l1[[2]]),4,4) %*% matrix(unlist(l2[[2]]),4,4) %*% matrix(unlist(l3[[2]]),4,4)
matrix(unlist(l1[[3]]),4,4) %*% matrix(unlist(l2[[3]]),4,4) %*% matrix(unlist(l3[[3]]),4,4)

Upvotes: 0

Related Questions