I have a list of lists called mylist. In the following example, mylist has two lists, in which contains another two lists of random numbers.
mylist <- list()
list1 <- rnorm(100)
list2 <- rnorm(100)
list3 <- rnorm(100)
list4 <- rnorm(100)
mylist[[1]] <- list("list1" = list1, "list2" = list2)
mylist[[2]] <- list("list1" = list3, "list2" = list4)
When printing the mylist, it should give us something like
[[1]]
[[1]]$list1
[1] 0.0382233645 0.2416676908 1.1910173996 0.7833025597 -0.7144370041
[6] 1.9762077872 0.9438593806 0.1590264664 -0.5323112247 1.2820246358...
[[1]]$list2
[1] -0.084982839 -0.462448106 0.771458598 1.354049503 -1.616381590 -0.368789648
[7] -0.678521566 -0.340799431 -0.441370037 -0.212117105 -0.921661840 0.893550382...
[[2]]
[[2]]$list1
[1] 0.367971534 0.028976364 1.391761655 -0.033661646 1.196138270 -1.645738949
[7] 0.086037770 0.530143788 0.639389906 2.193683933 -1.427285285 0.430282258...
[[2]]$list2
[1] 0.235027959 2.110340896 -0.951831561 -1.510063739 -0.007402732 -0.575736079
[7] -0.363731268 1.232404358 -0.848716435 1.217101680 -0.014577878 0.440142686...
I want to unlist mylist so that the final results (res) will output two elements. The first element will combine all available list1, and the second element will aggregate all available list2. The final results should look like
res$list1
[1] 0.0382233645 0.2416676908 1.1910173996 0.7833025597 -0.7144370041
[6] 1.9762077872 0.9438593806 0.1590264664 -0.5323112247 1.2820246358...
[101] 0.367971534 0.028976364 1.391761655 -0.033661646 1.196138270 -1.645738949
[107] 0.086037770 0.530143788 0.639389906 2.193683933 -1.427285285 0.430282258...
res$list2
[1] 0.367971534 0.028976364 1.391761655 -0.033661646 1.196138270 -1.645738949
[7] 0.086037770 0.530143788 0.639389906 2.193683933 -1.427285285 0.430282258...
[101] 0.235027959 2.110340896 -0.951831561 -1.510063739 -0.007402732 -0.575736079
[107] -0.363731268 1.232404358 -0.848716435 1.217101680 -0.014577878 0.440142686...
What is the right way to achieve that in R? Thanks!
We can use Map
to combine the sub-lists of each top-level list element.
Reproducible data:
set.seed(42)
mylist <- list()
list1 <- rnorm(5)
list2 <- rnorm(5)
list3 <- rnorm(5)
list4 <- rnorm(5)
mylist[[1]] <- list("list1" = list1, "list2" = list2)
mylist[[2]] <- list("list1" = list3, "list2" = list4)
mylist
# [[1]]
# [[1]]$list1
# [1] 1.3709584 -0.5646982 0.3631284 0.6328626 0.4042683
# [[1]]$list2
# [1] -0.10612452 1.51152200 -0.09465904 2.01842371 -0.06271410
# [[2]]
# [[2]]$list1
# [1] 1.3048697 2.2866454 -1.3888607 -0.2787888 -0.1333213
# [[2]]$list2
# [1] 0.6359504 -0.2842529 -2.6564554 -2.4404669 1.3201133
do.call(Map, args = c(list(f = c), mylist))
# $list1
# [1] 1.3709584 -0.5646982 0.3631284 0.6328626 0.4042683 1.3048697 2.2866454 -1.3888607 -0.2787888 -0.1333213
# $list2
# [1] -0.10612452 1.51152200 -0.09465904 2.01842371 -0.06271410 0.63595040 -0.28425292 -2.65645542 -2.44046693 1.32011335
If it's always list1
and list2
(a pre-known length within mylist
), then we can do away with do.call
and just use Map
directly:
Map(c, mylist[[1]], mylist[[2]])
The (sole?) benefit of using do.call
is that if mylist
is either unknown-length or long-length and you don't want to have to type in all of mylist[[1]]
, mylist[[2]]
, ..., mylist[[n]]
(which would work), then a simple expression handles it all for you.