Row bind all tibbles present in the nested list

Viewed 155

How to row bind all tibbles present in the nested list. Below is an example of four levels

combine all nested list elements to create a single tibble which has five columns -

  • first level list elements
  • second level list elements
  • third level list elements
  • fourth level list elements
  • p
library(dplyr)



tbl <- list()

a1 = runif(2)
a2 = runif(2)
a3 = runif(2)
a4 = runif(2)
a5 = runif(2)
a6 = runif(2)
a7 = runif(2)
a8 = runif(2)

tbl[["A"]][["m"]] [["a"]][["x"]] <- tibble(p = a1)
tbl[["A"]][["m"]] [["a"]][["y"]] <- tibble(p = a2)

tbl[["A"]][["m"]] [["b"]][["x"]] <- tibble(p = a3)
tbl[["A"]][["m"]] [["b"]][["y"]] <- tibble(p = a4)

tbl[["A"]][["n"]] [["a"]][["x"]] <- tibble(p = a5)
tbl[["A"]][["n"]] [["a"]][["y"]] <- tibble(p = a6)

tbl[["B"]][["n"]] [["b"]][["x"]] <- tibble(p = a7)
tbl[["A"]][["n"]] [["b"]][["y"]] <- tibble(p = a8)

tbl[["B"]][["m"]] [["a"]][["x"]] <- tibble(p = a1)
tbl[["B"]][["m"]] [["a"]][["y"]] <- tibble(p = a2)

tbl[["B"]][["m"]] [["b"]][["x"]] <- tibble(p = a3)
tbl[["B"]][["m"]] [["b"]][["y"]] <- tibble(p = a4)

tbl[["B"]][["n"]] [["a"]][["x"]] <- tibble(p = a5)
tbl[["B"]][["n"]] [["a"]][["y"]] <- tibble(p = a6)

tbl[["B"]][["n"]] [["b"]][["x"]] <- tibble(p = a7)
tbl[["B"]][["n"]] [["b"]][["y"]] <- tibble(p = a8)




# p

# expected results

tbl_expected <- tibble(first_element = c(rep("A", 16), rep("B", 16)),
                       
                       second_element = c(rep("m", 8), rep("n", 8), rep("m", 8), rep("n", 8)),
                       
                       third_element = c(rep("a", 4), rep("b", 4), rep("a", 4), rep("b", 4),
                                          rep("a", 4), rep("b", 4), rep("a", 4), rep("b", 4)),
                       
                       forth_element = c(rep("x", 2), rep("y", 2), rep("x", 2), rep("y", 2),
                                         rep("x", 2), rep("y", 2), rep("x", 2), rep("y", 2),
                                         rep("x", 2), rep("y", 2), rep("x", 2), rep("y", 2),
                                         rep("x", 2), rep("y", 2), rep("x", 2), rep("y", 2)),
                       
                     p = c(a1, a2, a3, a4, a5, a6, a7, a8, a1, a2, a3, a4, a5, a6, a7, a8))

1 Answers

We could use map with bind_rows while specifying the .id to create the inner and outer names of the nested list

library(purrr)
library(dplyr)
map_dfr(tbl, ~ bind_rows(.x, .id = 'second_element'),
     .id = 'first_element')

-output

# A tibble: 8 × 3
  first_element second_element      p
  <chr>         <chr>           <dbl>
1 a             x              0.307 
2 a             x              0.524 
3 a             y              0.827 
4 a             y              0.437 
5 b             x              0.236 
6 b             x              0.0944
7 b             y              0.590 
8 b             y              0.787 

With new dataset with more nesting, we may use a recursive function rrapply

library(rrapply)
library(tidyr)
rrapply(tbl, how = 'melt') %>% 
   unnest(value) %>%  
   select(-L5) %>% 
   set_names(c('first_element', 'second_element',
      'third_element', 'fourth_element',  'p')) 

-output

# A tibble: 30 × 5
   first_element second_element third_element fourth_element       p
   <chr>         <chr>          <chr>         <chr>            <dbl>
 1 A             m              a             x              0.409  
 2 A             m              a             x              0.782  
 3 A             m              a             y              0.832  
 4 A             m              a             y              0.769  
 5 A             m              b             x              0.365  
 6 A             m              b             x              0.401  
 7 A             m              b             y              0.00445
 8 A             m              b             y              0.667  
 9 A             n              a             x              0.00853
10 A             n              a             x              0.0553 
# … with 20 more rows
Related