Let's suppose I have a list of lists as follows:
set.seed(111)
lst_1 = rep(list(list()), 3)
lst_1[[1]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[2]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[3]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
where each list element (1, 2 and 3) is a list which contains two data.frames.
How can I sequentially bind the rows of the first data.frame
within each (sub)list? ie lst_1[[1]][[1]]
+ lst_1[[2]][[1]]
+ lst_1[[3]][[1]]
, and eventually do the same for the second data.frame
?
Here is my desired output, which is achieved manually with a for loop, however my real list of lists is much larger:
lst_out = rep(list(list()), 2)
for (i in 1:2) {
lst_out[[i]] = rbind(lst_1[[1]][[i]], lst_1[[2]][[i]], lst_1[[3]][[i]])
}
If I'm interpreting correctly, the base R solution should be pretty straight forward. Map
the rbind
function over each part of the 3 inputs in lst_1
:
do.call(Map, c(rbind, lst_1))
This is a slightly obscured way of calling the expanded Map
line of:
Map(rbind, lst_1[[1]], lst_1[[2]], lst_1[[3]])
Which starts to look a lot like your original for
loop, and gives the same result as doing it via do.call
:
identical(
do.call(Map, c(rbind, lst_1)),
Map(rbind, lst_1[[1]], lst_1[[2]], lst_1[[3]])
)
#[1] TRUE
Checks out with the intended result too:
identical(lst_out, do.call(Map, c(rbind, lst_1)))
#[1] TRUE
I think the simplest way is to simply purrr::transpose
the list, so that instead of three sublists with two dataframe elements, you have two sublists with three dataframe elements. This means that the dataframes to bind are all in the same sublist, so iteration is much simpler and we can map
over the main list. See below, noting that you can just load purrr
as dplyr::bind_rows
is just a bit faster and tibble::glimpse
is for printing only.
library(tidyverse)
set.seed(111)
lst_1 = rep(list(list()), 3)
lst_1[[1]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[2]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[3]] = list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1 %>%
transpose %>%
map(bind_rows) %>%
glimpse
#> List of 2
#> $ :'data.frame': 15 obs. of 1 variable:
#> ..$ rnorm.5.: num [1:15] 0.235 -0.331 -0.312 -2.302 -0.171 ...
#> $ :'data.frame': 15 obs. of 1 variable:
#> ..$ rnorm.5.: num [1:15] 0.14 -1.497 -1.01 -0.948 -0.494 ...
Created on 2019-04-20 by the reprex package (v0.2.1)
Base R solution
set.seed(111)
lst_1 <- rep(list(list()), 3)
lst_1[[1]] <- list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[2]] <- list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_1[[3]] <- list(data.frame(rnorm(5)), data.frame(rnorm(5)))
lst_out_2 <- list()
for (i in 1:2) {
lst_out_2[[i]] <- do.call('rbind', sapply(lst_1, `[`, i))
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.