Home > Enterprise >  Extract specific list elements from a nested list in R?
Extract specific list elements from a nested list in R?

Time:02-07

I have a nested list that looks like this:

x <- list(list(a = c(1,10), b=c(2,10)), list(c=c(3,10), d=c(6,10)), list(e= c(3,10)))
> x
[[1]]
[[1]]$a
[1]  1 10

[[1]]$b
[1]  2 10


[[2]]
[[2]]$c
[1]  3 10

[[2]]$d
[1]  6 10


[[3]]
[[3]]$e
[1]  3 10

I'm trying to extract just the first value from each list element. However, if the length of a list is greater than 1, then I want to add the extracted values together.

For example, in my list x above, we can see that the first list (i.e., x[[1]]) contains a and b... so I want to extract the 1st values from this list (in this case, 1 and 2) and since they belong to the same list, they get added together.

At the end, Im just trying to return a vector of the extracted (and where necessary, added) values. So in my example, I would expect a vector like: [1] 3 9 3.

CodePudding user response:

Using nested sapply -

sapply(x, function(y) sum(sapply(y, head, 1)))
#[1] 3 9 3

Or combine each list into a matrix and take sum of first column/row.

sapply(x, function(y) sum(do.call(rbind, y)[, 1]))
#sapply(x, function(y) sum(do.call(cbind, y)[1, ]))

CodePudding user response:

Here's another option using a nested map_dbl from purrr:

library(purrr)

map_dbl(x, ~sum(map_dbl(.x, 1)))
# [1] 3 9 3

CodePudding user response:

A fast rapply - vapply approach.

vapply(rapply(x, \(x) unlist(`[`(x, 1)), how='list'), \(x) sum(unlist(x)), 0)
# [1] 3 9 3

## microbenchmark ##
# Unit: microseconds
#   expr     min       lq      mean   median       uq      max neval cld
# sapply 124.166 128.4550 150.57375 131.5865 133.5845 2010.623   100  ab
# vapply  45.655  47.8645  84.40778  48.9600  49.7950 3583.235   100  a 
#  purrr 185.724 189.9295 194.47557 192.8915 195.6345  281.938   100   b
  •  Tags:  
  • Related