Earlien
Earlien

Reputation: 287

Separate a tibble column containing a list into multiple rows in R

A MWE of my situation is very similar to the example given in the help documentation for tidyr::separate_rows). A simplified version of this example is:

tibble(
  x = 1:3,
  y = c(list("3"), list("6, 7, 2"), list("4, 1"))       # Works
) %>%
separate_rows(y)

which gives

# A tibble: 6 x 2
      x     y
  <int> <chr>
1     1     3
2     2     6
3     2     7
4     2     2
5     3     4
6     3     1

My situation is that each element in y is a list, albeit with only one element, which is a vector.

tibble(
  x = 1:3,
  y = c(list(3), list(c(6, 7, 2)), list(c(4, 1)))     # Fails
) %>%
separate_rows(y)

which gives me the error:

Error: Can't combine `..1` <double> and `..2` <character>.

Note that in both cases, the y column in the tibble (before separate_rows) is a list class. Based on suggestions I've found elsewhere, I've tried using unnest and mutate_if(islist, ...) but cannot seem to get them to work.

There are many similar questions like this, but I haven't found any with the quite same situation as here.

Upvotes: 0

Views: 931

Answers (1)

AnilGoyal
AnilGoyal

Reputation: 26218

separate_rows is used to break a concatenated vector (not list column) into separate rows. Use unnest from tidyr to unnest elemnts of list-col into rows. This works

library(tibble)
library(tidyr)
tibble(
  x = 1:3,
  y = c(list(3), list(c(6, 7, 2)), list(c(4, 1))) 
)
#> # A tibble: 3 x 2
#>       x y        
#>   <int> <list>   
#> 1     1 <dbl [1]>
#> 2     2 <dbl [3]>
#> 3     3 <dbl [2]>

tibble(
  x = 1:3,
  y = c(list(3), list(c(6, 7, 2)), list(c(4, 1))) 
) %>% unnest(y)
#> # A tibble: 6 x 2
#>       x     y
#>   <int> <dbl>
#> 1     1     3
#> 2     2     6
#> 3     2     7
#> 4     2     2
#> 5     3     4
#> 6     3     1

If you still want to use separate_rows collapse elements of list-column to a single element vector. But it will result in coercing the double type elements to character type.

tibble(
  x = 1:3,
  y = c(list(3), list(c(6, 7, 2)), list(c(4, 1))) 
) %>% 
  mutate(y = map_chr(y, ~paste(.x, collapse = ', '))) %>%
  separate_rows(y, sep = ', ')

# A tibble: 6 x 2
      x y    
  <int> <chr>
1     1 3    
2     2 6    
3     2 7    
4     2 2    
5     3 4    
6     3 1

Upvotes: 2

Related Questions