rlistmatrixnestedelementwise-operations

element-wise averages of two (or more) nested lists of matrices


I have two lists A_1 and A_2, each contains two matrices.

A_1 <- list(a=matrix(1:8, 2), b=matrix(2:9, 2))

A_2 <- list(a=matrix(10:17, 2), b=matrix(5:12, 2))

I'd like to calculate element-wise averages of these two lists which results a list of

tibble::lst((A_1$a + A_2$a)/2, (A_1$b + A_2$b)/2)

I used

purrr::pmap(list(A_1 , A_2), mean)

but got

Error in mean.default(.l[[1L]][[i]], .l[[2L]][[i]], ...) : 
  'trim' must be numeric of length one`  

or

purrr::map2(A_1, A_2, mean)

Error in mean.default(.x[[i]], .y[[i]], ...) : 
  'trim' must be numeric of length one`

Solution

  • In base R, We could use:

    A <-list(A_1, A_2)
    lapply(Reduce(\(x, y)Map('+', x, y), A), '/', length(A))
    
    $a
         [,1] [,2] [,3] [,4]
    [1,]  5.5  7.5  9.5 11.5
    [2,]  6.5  8.5 10.5 12.5
    
    $b
         [,1] [,2] [,3] [,4]
    [1,]  3.5  5.5  7.5  9.5
    [2,]  4.5  6.5  8.5 10.5
    

    This code is generic in that we can use to find the mean of several lists. Note that A_1 and A_2 must have the same number of matrices, not necessarily 2. Can be 10 etc. Also note that each corresponding matrix has the same dimensions. Example below:

    B_1 <- list(matrix(c(1,2,3,4), 2), matrix(c(1,3,4,2), 2),
                matrix(c(1:10), 5), matrix(c(1:20), 5))
    B_2 <- lapply(B_1, '*', 2) # In this case, its B_1 * 2
    B_3 <- lapply(B_2, '*', 3) #
    

    Now you could use the code provide above:

    B <-list(B_1, B_2, B_3)
    lapply(Reduce(\(x, y)Map('+', x, y), B), '/', length(B))