Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unnest column-list?

Tags:

r

tidyverse

I have a tibble like:

tibble(a = c('first', 'second'), 
       b = list(c('colA' = 1, 'colC' = 2), c('colA'= 3, 'colB'=2))) 

# A tibble: 2 x 2
  a      b        
  <chr>  <list>   
1 first  <dbl [2]>
2 second <dbl [2]>

Which a would like to turn into this form:

# A tibble: 2 x 4
  a       colA  colB  colC
  <chr>  <dbl> <dbl> <dbl>
1 first     1.   NA     2.
2 second    3.    2.   NA 

I tried to use unnest(), but I am having issues preserving the elements' names from the nested values.

like image 939
Dambo Avatar asked Apr 18 '18 00:04

Dambo


People also ask

How do I Unnest a column in R?

The tidyr package in R is used to “tidy” up the data. The unnest() method in the package can be used to convert the data frame into an unnested object by specifying the input data and its corresponding columns to use in unnesting. The output is produced in the form of a tibble in R.

How do I Unnest a list of Dataframes in R?

: all list-columns are now preserved; If there are any that you don't want in the output use select() to remove them prior to unnesting. : convert df %>% unnest(x, . id = "id") to df %>% mutate(id = names(x)) %>% unnest(x)) . : use names_sep instead.

What does Nest () do in R?

Nesting creates a list-column of data frames; unnesting flattens it back out into regular columns. Nesting is a implicitly summarising operation: you get one row for each group defined by the non-nested columns. This is useful in conjunction with other summaries that work with whole datasets, most notably models.

What is Unnest function?

The UNNEST function returns a result table that includes a row for each element of the specified array. If there are multiple ordinary array arguments specified, the number of rows will match the array with the largest cardinality.


2 Answers

You can do this by coercing the elements in the list column to data frames arranged as you like, which will unnest nicely:

library(tidyverse)

tibble(a = c('first', 'second'), 
       b = list(c('colA' = 1, 'colC' = 2), c('colA'= 3, 'colB'=2))) %>% 
    mutate(b = invoke_map(tibble, b)) %>% 
    unnest()
#> # A tibble: 2 x 4
#>   a       colA  colC  colB
#>   <chr>  <dbl> <dbl> <dbl>
#> 1 first     1.    2.   NA 
#> 2 second    3.   NA     2.

Doing the coercion is a little tricky, though, as you don't want to end up with a 2x1 data frame. There are various ways around this, but a direct route is purrr::invoke_map, which calls a function with purrr::invoke (like do.call) on each element in a list.

like image 155
alistaire Avatar answered Oct 18 '22 22:10

alistaire


With tidyr 1.0.0, we can use unnest_wider to directly add new columns.

tidyr::unnest_wider(df,b)
# A tibble: 2 x 4
#  a       colA  colC  colB
#  <chr>  <dbl> <dbl> <dbl>
#1 first      1     2    NA
#2 second     3    NA     2

data

df <- tibble(a = c('first', 'second'), 
   b = list(c('colA' = 1, 'colC' = 2), c('colA'= 3, 'colB'=2)))
like image 2
Ronak Shah Avatar answered Oct 18 '22 23:10

Ronak Shah