R apply function on nested list elements based on matching nested list names

Viewed 166

Say I have a named nested list l consisting of sub-lists of named numeric vectors, each of length 1:

l <- list("L1" = list('a' = 1, 'b' = 2), "L2" = list('a'= 2, 'c' = 1, 'd' = 1))

I am struggling to find a way in base R to apply a function such as sum for all matching sub-list with similar name (e.g. l$L1$a and l$L2$a whose sum would be 3). The result from applied using sum in l would be for instance a named vector res:

> res
a b c d 
3 2 1 1

In (my) real life the list l has variable and unknown numbers and lengths of sub-lists L1, L2, ... , and similar, the names and numbers of the numeric vectors to be summed (a, b, ...) are also variable and unknown. However, the depth of the list is always as shown.

2 Answers

One dplyr option could be:

bind_rows(l) %>%
 summarise_all(~ sum(., na.rm = TRUE))

      a     b     c     d
  <dbl> <dbl> <dbl> <dbl>
1     3     2     1     1

We can use unnest_wider

library(tibble)
library(tidyr)
tibble(col = l) %>%
    unnest_wider(col) %>% 
    summarise_all(sum, na.rm = TRUE)
# A tibble: 1 x 4
#      a     b     c     d
#   <dbl> <dbl> <dbl> <dbl>
#1     3     2     1     1

Or using base R with aggregate

aggregate(values ~ ind, do.call(rbind, lapply(l, stack)), sum)

Or rowsum

with(do.call(rbind, lapply(l, stack)), rowsum(values, ind))

Or with tapply

with(do.call(rbind, lapply(l, stack)), tapply(values, ind, sum))
# a b c d 
#3 2 1 1 
Related