Unlist heterogeneous, named column-list into several columns (tidyr)

Hi RStudio Community!

I thank you very, very much in advance for all of your replies!

I have a tibble (input_tbl) with names (character column) and a list column (my_list ). For each name, I have a some numeric values (numbers_x) and some character values (name_x) inside the list column. The thing is that those are in a named, column-list of different dimensions. See the reprex below for a better understanding, but I'll try to explain the example below:

name a has 3 integer values and 3 character values. name b has 7 integer values and 7 character values. All of these lie within a list-column:input_tbl$values. My goal is to take all of the integers and take them to a new column with 3+7 = 10 integers, and all the characters and take them to a column with 10 characters.

As you can see, I've tried some functions such as: tidyr::hoist(), tidyr::unnest_wider() but I haven't had success.

library(tidyverse)
#> Warning: package 'tibble' was built under R version 4.0.3
library(reprex)



# --- named list ---
my_list <- list(
  numbers_1 = 1:3,
  name_1 = paste0("character", 1:3),
  numbers_2 = 4:10,
  name_2 = paste0("character", 4:10)
)

my_list
#> $numbers_1
#> [1] 1 2 3
#> 
#> $name_1
#> [1] "character1" "character2" "character3"
#> 
#> $numbers_2
#> [1]  4  5  6  7  8  9 10
#> 
#> $name_2
#> [1] "character4"  "character5"  "character6"  "character7"  "character8" 
#> [6] "character9"  "character10"

# --- input tibble ---
input_tbl <- tibble(
  name = c("a", "a", "b", "b"),
  values = my_list
)

input_tbl
#> # A tibble: 4 x 2
#>   name  values      
#>   <chr> <named list>
#> 1 a     <int [3]>   
#> 2 a     <chr [3]>   
#> 3 b     <int [7]>   
#> 4 b     <chr [7]>

# --- desired tibble ---
target_tbl <- tibble(
  name = c(rep("a", 3), rep("b", 7)),
  values_int = c(1:3, 4:10),
  values_chr = c(paste0("character", 1:3), paste0("character", 4:10))
)

target_tbl
#> # A tibble: 10 x 3
#>    name  values_int values_chr 
#>    <chr>      <int> <chr>      
#>  1 a              1 character1 
#>  2 a              2 character2 
#>  3 a              3 character3 
#>  4 b              4 character4 
#>  5 b              5 character5 
#>  6 b              6 character6 
#>  7 b              7 character7 
#>  8 b              8 character8 
#>  9 b              9 character9 
#> 10 b             10 character10



# errors:

# obviously failed with unnest because the list is heterogeneous
input_tbl %>% 
  unnest(cols = c(values))
#> Error: Can't combine `..1$values` <integer> and `..2$values` <character>.


# failed to use unnest_wider
input_tbl %>% 
  unnest_wider(col = values)
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> * `` -> ...3
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> * `` -> ...3
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> * `` -> ...3
#> * `` -> ...4
#> * `` -> ...5
#> * ...
#> New names:
#> * `` -> ...1
#> * `` -> ...2
#> * `` -> ...3
#> * `` -> ...4
#> * `` -> ...5
#> * ...
#> Error: Can't combine `..1$...1` <integer> and `..2$...1` <character>.

# failed with hoist
input_tbl %>% 
  hoist(.col = values)
#> Error: All elements of `...` must be named

Created on 2020-10-21 by the reprex package (v0.3.0)

input_tbl2 <- mutate(rowwise(input_tbl),
                     values=list(as.character(values)))
unnest(input_tbl2,cols=c(values))
input_tbl %>% 
  mutate(what = map_chr(values, typeof)) %>% 
  pivot_wider(names_from = what, values_from = values,
              names_glue = '{.value}_{abbreviate(what, 3)}') %>% 
  unnest(-name)

#> # A tibble: 10 x 3
#>    name  values_int values_chr 
#>    <chr>      <int> <chr>      
#>  1 a              1 character1 
#>  2 a              2 character2 
#>  3 a              3 character3 
#>  4 b              4 character4 
#>  5 b              5 character5 
#>  6 b              6 character6 
#>  7 b              7 character7 
#>  8 b              8 character8 
#>  9 b              9 character9 
#> 10 b             10 character10

Created on 2020-10-21 by the reprex package (v0.3.0)

2 Likes

These are awesome!! Thank you so much for the answer! I would've never thought of using map_chr to go inside the list's values a fetch the type!! That's so clever @jmcvw!!!

Best,
Alexis

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.