Sum across list elements whose sub-elements have the same name

Viewed 55

List to reproduce the Minimal Working Example

Suppose I have a list like this

a <- list(
    list(
        a=matrix(c(1, 2)), 
        b=matrix(c(1,2,1,2), ncol=2)),
    list(
        a=matrix(c(3, 5)), 
        b=matrix(c(5,2,7,1), ncol=2))
)

It basically looks like this

[[1]]
[[1]]$a
     [,1]
[1,]    1
[2,]    2

[[1]]$b
     [,1] [,2]
[1,]    1    1
[2,]    2    2


[[2]]
[[2]]$a
     [,1]
[1,]    3
[2,]    5

[[2]]$b
     [,1] [,2]
[1,]    5    7
[2,]    2    1

Desired Output

I would like, for every element of a, to find the sum over the correct name. In this case I would like to be able to have an output similar to this (although doesn't need to be a list)

$a
     [,1]
[1,]    4
[2,]    7

$b
     [,1] [,2]
[1,]    6    8
[2,]    4    3

What is the fastest way to obtain this output? I can do this with a for-loop, but I'm sure there must be a better way.

2 Answers

Use transpose to exchange inner and outer lists. Then use map and reduce to sum up.

library(purrr)

a %>%
  transpose %>%
  map(~ reduce(., `+`))

# $a
#      [,1]
# [1,]    4
# [2,]    7
# 
# $b
#      [,1] [,2]
# [1,]    6    8
# [2,]    4    3

In base R you could do.

Map(function(i) a[[1]][[i]] + a[[2]][[i]], el(Map(names, a)))

Or, more generally

sapply(el(Map(names, a)), function(i) Reduce(`+`, mapply(`[`, a, i)))
# $a
#      [,1]
# [1,]    4
# [2,]    7
# 
# $b
#      [,1] [,2]
# [1,]    6    8
# [2,]    4    3
Related