Errors in `as_tibble()` for a list of lists with different lengths

I am not familiar with tibble, I wanted to turn a list of lists with different depths into tibble, but I got the following errors using as_tibble():

> not.ok.list <- list(a = 'a', 
+                     b = paste0(rep('b', 4), c(1:4)), 
+                     c = paste0(rep('c', 5), c(1:5)))

> as_tibble(not.ok.list)

Error: Tibble columns must have compatible sizes.
* Size 4: Column `b`.
* Size 5: Column `c`.
ℹ Only values of size one are recycled.

But it's ok with a list of lists with same depths (others are character or something):

> ok.list <- list(a = 'a', 
+                 b = paste0(rep('b', 4), c(1:4)), 
+                 c = paste0(rep('c', 4), c(1:4)))

> as_tibble(ok.list)
# A tibble: 4 x 3
  a     b     c    
  <chr> <chr> <chr>
1 a     b1    c1   
2 a     b2    c2   
3 a     b3    c3   
4 a     b4    c4  

I was wondering if there is a way to generate the tibble like:

# expected output for not.ok.list
# A tibble: 1 x 3
  a     b          c    
  <chr> <list>     <list>
1 a     <list [4]> <list [5]>   

Many thanks!

Not exactly your desired output but you could consider tibble::enframe() and transform the result.

library(tibble)

not.ok.list <- list(
  a = "a",
  b = paste0(rep("b", 4), c(1:4)),
  c = paste0(rep("c", 5), c(1:5))
)

enframe(not.ok.list)
#> # A tibble: 3 x 2
#>   name  value    
#>   <chr> <list>   
#> 1 a     <chr [1]>
#> 2 b     <chr [4]>
#> 3 c     <chr [5]>

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

1 Like

You have the answer in your example. not.ok.list doesn't work because its columns would be different lengths. To make it as a tibble, it would work if columns b and c were lists of length 1, containing their lists of lengths 4 or 5.

not.ok.list2 <- list(a = 'a',
                    b = list(paste0(rep('b', 4), c(1:4))), 
                    c = list(paste0(rep('c', 5), c(1:5))))

as_tibble(not.ok.list2)
# A tibble: 1 x 3
#     a     b         c        
#     <chr> <list>    <list>   
#   1 a     <chr [4]> <chr [5]>

Note here the content of b[[1]] is a chr vector, not a list as in your example. That's not hard to change though, with b = list(as.list(paste0(rep('b', 4), c(1:4)))).

Also note the enframed version from siddharthprabhu is probably more useful in practice.

1 Like

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