Reputation: 366
I have lists deep within lists and I want to extract all matrices with name a
from the code below and store all these matrices into asingle list, say matlist
. Please can anyone suggest how to do this. Thank you in advance
x <- list()
x[[1]] <- list()
x[[1]][[1]] <- list()
x[[1]][[2]] <- list()
x[[2]] <- list()
x[[2]][[1]] <- list()
x[[2]][[2]] <- list()
x[[3]] <- list()
x[[3]][[1]] <- list()
x[[3]][[2]] <- list()
x[[1]][[1]]$a <- matrix(rnorm(4),2,2)
x[[1]][[1]]$b <- 3
x[[1]][[2]]$a <- matrix(rnorm(4),2,2)
x[[1]][[2]]$b <- 3
x[[2]][[1]]$a <- matrix(rnorm(4),2,2)
x[[2]][[1]]$b <- 2
x[[2]][[2]]$a <- matrix(rnorm(4),2,2)
x[[2]][[2]]$b <- 2
x[[3]][[1]]$a <- matrix(rnorm(4),2,2)
x[[3]][[1]]$b <- 1
x[[3]][[2]]$a <- matrix(rnorm(4),2,2)
x[[3]][[2]]$b <- 1
Upvotes: 0
Views: 323
Reputation: 39647
You can use [[
in lapply
with a
after using unlist
for one level to extract lists within lists based on variable name.
matlist <- lapply(unlist(x, FALSE), "[[", "a")
matlist
#[[1]]
# [,1] [,2]
#[1,] -0.2164749 0.1255995
#[2,] 0.9368159 1.0416349
#
#[[2]]
# [,1] [,2]
#[1,] -2.188259 -0.2364393
#[2,] -3.003292 1.2006254
#
#[[3]]
# [,1] [,2]
#[1,] 1.089767 1.059162
#[2,] -2.043437 1.428467
#
#[[4]]
# [,1] [,2]
#[1,] -0.1984872 1.194170
#[2,] -0.9998112 -2.875852
#
#[[5]]
# [,1] [,2]
#[1,] 1.4556923 -0.05156698
#[2,] -0.4252525 -0.64838966
#
#[[6]]
# [,1] [,2]
#[1,] 0.2450849 0.6129029
#[2,] -0.2372427 0.2555269
Or in case you want to keep the structure of sub lists like purrr:map_depth
is doing a recursive function call is possible:
f <- function(x, n) {
if(!is.null(names(x)) & n %in% names(x)) x[[n]]
else if(is.list(x)) lapply(x, f, n)
}
matlist <- f(x, "a")
matlist
#[[1]]
#[[1]][[1]]
# [,1] [,2]
#[1,] -0.2164749 0.1255995
#[2,] 0.9368159 1.0416349
#
#[[1]][[2]]
# [,1] [,2]
#[1,] -2.188259 -0.2364393
#[2,] -3.003292 1.2006254
#
#
#[[2]]
#[[2]][[1]]
# [,1] [,2]
#[1,] 1.089767 1.059162
#[2,] -2.043437 1.428467
#
#[[2]][[2]]
# [,1] [,2]
#[1,] -0.1984872 1.194170
#[2,] -0.9998112 -2.875852
#
#
#[[3]]
#[[3]][[1]]
# [,1] [,2]
#[1,] 1.4556923 -0.05156698
#[2,] -0.4252525 -0.64838966
#
#[[3]][[2]]
# [,1] [,2]
#[1,] 0.2450849 0.6129029
#[2,] -0.2372427 0.2555269
Upvotes: 1
Reputation: 388817
You can use lapply
as :
lapply(x, function(x) {
x1 <- unlist(x, recursive = FALSE)
do.call(rbind, x1[names(x1) == 'a'])
}) -> x1
x1
#[[1]]
# [,1] [,2]
#[1,] 0.3031708 0.09749503
#[2,] 0.9608749 0.51528005
#[3,] -0.6591001 0.09854767
#[4,] -1.6979551 -0.11709249
#[[2]]
# [,1] [,2]
#[1,] -1.11747169 -0.5668559
#[2,] -0.87458122 0.2517329
#[3,] -0.01483449 -1.7775506
#[4,] 1.57139735 -0.3488897
#[[3]]
# [,1] [,2]
#[1,] -0.2880580 -0.07233675
#[2,] 0.2933759 0.73729995
#[3,] 0.1070971 -0.27202774
#[4,] -0.5881883 -1.27391810
If you want everything combined into one you can do do.call(rbind, x1)
.
Upvotes: 1
Reputation: 1860
This time purrr:map_depth
is your friend:
library(purrr)
map_depth(x, .depth = 2, 'a')
[[1]]
[[1]][[1]]
[,1] [,2]
[1,] 2.0693923 2.142611
[2,] 0.6840833 -1.440975
[[1]][[2]]
[,1] [,2]
[1,] 0.5415685 -0.7262725
[2,] -0.1604015 0.5218570
[[2]]
[[2]][[1]]
[,1] [,2]
[1,] 0.1245714 8.887078e-05
[2,] -0.2137517 -9.737122e-01
[[2]][[2]]
[,1] [,2]
[1,] 0.1993254 0.1116033
[2,] 0.5058125 -1.8523019
[[3]]
[[3]][[1]]
[,1] [,2]
[1,] 0.8661770 -1.76328811
[2,] -0.4559405 -0.08104821
[[3]][[2]]
[,1] [,2]
[1,] 0.7247404 -2.6736933
[2,] 0.8053027 0.5735254
Upvotes: 1