Home > Net >  Rbind on dataframes in nested list/tibbles
Rbind on dataframes in nested list/tibbles

Time:09-03

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

CodePudding user response:

You could use map_dfr bind_rows:

library(tidyverse)

map_dfr(list_graphs, ~ bind_rows(.x, .id = "species"), .id = "season")

# # A tibble: 6 × 3
#   season species      x
#   <chr>  <chr>    <dbl>
# 1 winter species1     1
# 2 winter species2     2
# 3 winter species3     3
# 4 summer species1     4
# 5 summer species2     5
# 6 summer species3     6

Data
list_graphs <- list(winter = list(species1 = tibble(x = 1), species2 = tibble(x = 2), species3 = tibble(x = 3)),
                    summer = list(species1 = tibble(x = 4), species2 = tibble(x = 5), species3 = tibble(x = 6)))

glimpse(list_graphs)

# List of 2
#  $ winter:List of 3
#   ..$ species1: tibble [1 × 1] (S3: tbl_df/tbl/data.frame)
#   ..$ species2: tibble [1 × 1] (S3: tbl_df/tbl/data.frame)
#   ..$ species3: tibble [1 × 1] (S3: tbl_df/tbl/data.frame)
#  $ summer:List of 3
#   ..$ species1: tibble [1 × 1] (S3: tbl_df/tbl/data.frame)
#   ..$ species2: tibble [1 × 1] (S3: tbl_df/tbl/data.frame)
#   ..$ species3: tibble [1 × 1] (S3: tbl_df/tbl/data.frame)

CodePudding user response:

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
  • Related