Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unnest_wider() with loop over all the columns containing lists?

Tags:

r

dplyr

tidyr

I have following data

A   B            C             D
1   1501583974   <list [3]>  <tibble>
1   1501616585   <list [3]>  <tibble>
1   1501583344   <list [3]>  <tibble>
1   1501573386   <list [3]>  <tibble>

Code I have used

data %>%
unnest_wider(c, names_sep="_") %>%
unnest_wider(d, names_sep="_")

Gives output

    A   B            C_1  C_2 C_3  D_1         D_2   
    1   1501583974   1    2   3   <list [1]>  <list [1]>
    1   1501616585   1    2   3   <list [1]>  <list [1]>
    1   1501583344   1    2   3   <list [1]>  <list [1]>
    1   1501573386   1    2   3   <list [1]>  <list [1]>

and then unnest_wider() again on all the columns is very tedious.
How to design a loop which works until all the columns with lists are not unnested?

Thanks

like image 944
Rohan Kataria Avatar asked Nov 01 '25 08:11

Rohan Kataria


1 Answers

Here is a data frame with nested list and data frame columns.

library(tidyverse)

l <- list(y1 = 1, y2 = list(z1 = 1))

data <- tribble(
  ~x1,  ~list1,     ~tibble1,
    1,       l, as.tibble(l),
    1,       l, as.tibble(l),
    1,       l, as.tibble(l),
    1,       l, as.tibble(l)
)
data
#> # A tibble: 4 x 3
#>      x1 list1            tibble1         
#>   <dbl> <list>           <list>          
#> 1     1 <named list [2]> <tibble [1 × 2]>
#> 2     1 <named list [2]> <tibble [1 × 2]>
#> 3     1 <named list [2]> <tibble [1 × 2]>
#> 4     1 <named list [2]> <tibble [1 × 2]>

We can create a function, unnest_all, which recursively unnests all the list columns.

  • First, it finds all the list columns.
  • Then, if there are any list columns, it unnests each of them.
  • Finally, it calls unnest_all again to unnest any remaining list columns.
unnest_all <- function(df) {
  list_columns <- df %>% keep(is.list) %>% names()
  
  if (length(list_columns) == 0) {
    return(df)
  }

  for (list_column in list_columns) {
    df <-
      df %>%
      unnest_wider(list_column, names_sep = "_")
  }
  unnest_all(df)
}
unnest_all(data)
#> # A tibble: 4 x 5
#>      x1 list1_y1 list1_y2_z1 tibble1_y1 tibble1_y2_z1
#>   <dbl>    <dbl>       <dbl>      <dbl>         <dbl>
#> 1     1        1           1          1             1
#> 2     1        1           1          1             1
#> 3     1        1           1          1             1
#> 4     1        1           1          1             1
like image 51
Paul Avatar answered Nov 03 '25 22:11

Paul