D Greenwood
D Greenwood

Reputation: 436

Convert list of lists into single nested row of a data.frame or tibble (R)

I have a nested list of lists:

data = list(a = list(1, 2, 3), b = list("foo"), c = list("toast", "onions"))

How can I convert this into a single row of a data.frame or tibble? I would like the lists with more than one element (a and c here) to be kept as lists, and the single-element (b) to be a regular value.

Expected output is:

# A tibble: 1 x 3
  a          b     c         
  <list>     <chr> <list>    
1 <list [3]> foo   <list [2]>

Upvotes: 5

Views: 792

Answers (4)

akrun
akrun

Reputation: 887138

An option is to create a two column dataset with aggregate from base R

aggregate(values ~ ind, stack(data), list)

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388982

You can use enframe + pivot_wider

tibble::enframe(data) %>% tidyr::pivot_wider() 
#      a          b          c         
#  <list>     <list>     <list>    
#1 <list [3]> <list [1]> <list [2]>

To get length one column as vector we can add :

library(dplyr)

tibble::enframe(data) %>% 
  tidyr::pivot_wider() %>%
  summarise(across(.fns = ~if(length(unlist(.)) == 1) unlist(.) else .))

#      a          b     c         
#  <list>     <chr> <list>    
#1 <list [3]> foo   <list [2]>

Upvotes: 1

s_baldur
s_baldur

Reputation: 33488

data[] <- lapply(data, function(x) if (length(x) == 1) x[[1]] else list(x))
data.table::setDF(data)

# > str(data)
# 'data.frame': 1 obs. of  3 variables:
#  $ a:List of 1
#   ..$ :List of 3
#   .. ..$ : num 1
#   .. ..$ : num 2
#   .. ..$ : num 3
#  $ b: chr "foo"
#  $ c:List of 1
#   ..$ :List of 2
#   .. ..$ : chr "toast"
#   .. ..$ : chr "onions"

Upvotes: 1

ThomasIsCoding
ThomasIsCoding

Reputation: 101403

What about this?

> as_tibble_row(Map(function(x) ifelse(length(x)==1,unlist(x),list(x)),data))
# A tibble: 1 x 3
  a          b     c
  <list>     <chr> <list>
1 <list [3]> foo   <list [2]>

Upvotes: 2

Related Questions