bretauv
bretauv

Reputation: 8557

Bind rows of tibbles in a nested list with a loop, whatever the number of tibbles

I have several lists (that I call sub-lists) nested in a unique list (that we call supra-list). Each sub-list contains several elements that are tibbles. Each sub-list has a number of elements between 1 and 8 but that differs from a sub-list to the other. Whatever the number of elements / tibbles in a sub-list, I would like to bind the rows of these elements / tibbles so that each element of the supra-list is a big tibble.

I know how to access elements of nested lists but the problem is that the number of elements is not identical in each sub-list so I don't know how to make this in a loop.

How can I create a loop that binds all tibbles in sub-lists, whatever the number of tibbles?

Here's a reproducible example:

library(tibble)
library(dplyr)

data1 <- tibble(id = rep(1, 26),
                x = letters)

data2 <- tibble(id = rep(2, 26),
                x = letters)

data3 <- tibble(id = rep(3, 26),
                x = letters)

list_one <- list(data1, data2)
list_two <- list(data1, data2, data3)

full_list <- list()
full_list[["list_one"]] <- list_one
full_list[["list_two"]] <- list_two

and this is the expected result:

result <- list()
result[["list_one"]] <- bind_rows(data1, data2)
result[["list_two"]] <- bind_rows(data1, data2, data3)

> result
$list_one
# A tibble: 52 x 2
      id x    
   <dbl> <chr>
 1     1 a    
 2     1 b    
 3     1 c    
 4     1 d    
 5     1 e    
 6     1 f    
 7     1 g    
 8     1 h    
 9     1 i    
10     1 j    
# … with 42 more rows

$list_two
# A tibble: 78 x 2
      id x    
   <dbl> <chr>
 1     1 a    
 2     1 b    
 3     1 c    
 4     1 d    
 5     1 e    
 6     1 f    
 7     1 g    
 8     1 h    
 9     1 i    
10     1 j    
# … with 68 more rows

Upvotes: 0

Views: 1788

Answers (2)

Richard M
Richard M

Reputation: 25

   library(dplyr)
   blist <- function(list) {
   #This collect the total number of elements in a list
   number_lists <- length(list)
   # You may run this directly without wrapping it in a function. Just replace 
   number list with the position of the last list list you want to include in the 
   new data frame
   ndf <- bind_rows(list[1:number_lists])
   return(ndf)
   }
   blist(list_one)
   blist(list_two)

Upvotes: 0

Bas
Bas

Reputation: 4658

You want to map over the list and apply a function (bind_rows) to every element (which is in your case again a list).

I would do the mapping with purrr:

purrr::map(full_list, bind_rows)

but it can also be done with base R as Ronak commented:

lapply(full_list, function(x) do.call(rbind, x))

Upvotes: 2

Related Questions