Search code examples
rnestedpurrr

Rbind on dataframes in nested list/tibbles


I have nested tibbles, within a list, within a list, here's the structure:

I basically need to rbind the dataframes that are inside everything. The result would be 6 dataframes in a list, one for each season(winter/summer) and species combination.

> glimpse(list_graphs)

List of 2
 $ winter:List of 3
  ..$ species1: tibble [161 x 1] (S3: tbl_df/tbl/data.frame)
  ..$ species2: tibble [38 x 1] (S3: tbl_df/tbl/data.frame)
  ..$ species3: tibble [72 x 1] (S3: tbl_df/tbl/data.frame)
 $ summer:List of 3
  ..$ species1: tibble [33 x 1] (S3: tbl_df/tbl/data.frame)
  ..$ species2: tibble [2 x 1] (S3: tbl_df/tbl/data.frame)
  ..$ species3: tibble [52 x 1] (S3: tbl_df/tbl/data.frame)

I've tried:

map(list_graphs, function(x) {
  map(x, function(x){
    map(x,~do.call(rbind,x))
    }
  )
})

However, this results in the following which is incorrect:

List of 2
 $ winter:List of 3
  ..$ species1:List of 1
  .. ..$ graph_layer:List of 161
  .. .. ..- attr(*, "dim")= int [1:2] 1 161
  .. .. ..- attr(*, "dimnames")=List of 2
  ..$ species2:List of 1
  .. ..$ graph_layer:List of 38
  .. .. ..- attr(*, "dim")= int [1:2] 1 38
  .. .. ..- attr(*, "dimnames")=List of 2
  ..$ species3:List of 1
  .. ..$ graph_layer:List of 72
  .. .. ..- attr(*, "dim")= int [1:2] 1 72
  .. .. ..- attr(*, "dimnames")=List of 2
 $ summer:List of 3
  ..$ species1:List of 1
  .. ..$ graph_layer:List of 33
  .. .. ..- attr(*, "dim")= int [1:2] 1 33
  .. .. ..- attr(*, "dimnames")=List of 2
  ..$ species2:List of 1
  .. ..$ graph_layer:List of 2
  .. .. ..- attr(*, "dim")= int [1:2] 1 2
  .. .. ..- attr(*, "dimnames")=List of 2
  ..$ species3:List of 1
  .. ..$ graph_layer:List of 52
  .. .. ..- attr(*, "dim")= int [1:2] 1 52
  .. .. ..- attr(*, "dimnames")=List of 2

I'm sure it's a relatively easy fix, but I just can't work it out. I'm hoping someone can suggest solution based on structure I have above, if not I'll try and get a working regex dataframe.

Thank you


Solution

  • Since you don't provide a reproducible example, here's how I understand what you are dealing with:

    You have (something like)

    l <- list(
          winter = list(
            species1 = list(tibble(x = 1), tibble(x = 2), tibble(x = 3)), 
            species2 = list(tibble(x = 4), tibble(x = 5), tibble(x = 6)), 
            species3 = list(tibble(x = 7), tibble(x = 8), tibble(x = 9)) 
            ),
         summer = list(
           species1 = list(tibble(x = 10), tibble(x = 11), tibble(x = 12)), 
           species2 = list(tibble(x = 13), tibble(x = 14), tibble(x = 15)), 
           species3 = list(tibble(x = 16), tibble(x = 17), tibble(x = 18)) 
         )
        )
    

    Here's an approach that preserves names and returns a list of (row-bound) tibbles:

    map(names(l), function(name) set_names( 
                                  map(l[[name]], ~ map_dfr(.x, ~ .x)), 
                                  paste0, name
                                 )
      ) %>% 
       flatten()
    

    Outcome (of str() for brevity)

    List of 6
     $ species1winter: tibble [3 × 1] (S3: tbl_df/tbl/data.frame)
      ..$ x: num [1:3] 1 2 3
     $ species2winter: tibble [3 × 1] (S3: tbl_df/tbl/data.frame)
      ..$ x: num [1:3] 4 5 6
     $ species3winter: tibble [3 × 1] (S3: tbl_df/tbl/data.frame)
      ..$ x: num [1:3] 7 8 9
     $ species1summer: tibble [3 × 1] (S3: tbl_df/tbl/data.frame)
      ..$ x: num [1:3] 10 11 12
     $ species2summer: tibble [3 × 1] (S3: tbl_df/tbl/data.frame)
      ..$ x: num [1:3] 13 14 15
     $ species3summer: tibble [3 × 1] (S3: tbl_df/tbl/data.frame)
      ..$ x: num [1:3] 16 17 18