Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create list of lists from tibble in R (tidyverse)

I'm trying to do something that seems very simple, but I cannot figure it out. I have a tibble like so:

> df <- tibble::tribble(
  ~col_a, ~col_b,
  1,      "A",   
  2,      "B",   
  3,      "C",   
)
> df
# # A tibble: 3 x 2
# col_a col_b
# <dbl> <chr>
#   1     A    
#   2     B    
#   3     C 

and I want to turn it into a list that looks like this

> str(res_list)
# List of 3
# $ :List of 2
# ..$ col_a: num 1
# ..$ col_b: chr "A"
# $ :List of 2
# ..$ col_a: num 2
# ..$ col_b: chr "B"
# $ :List of 2
# ..$ col_a: num 3
# ..$ col_b: chr "C"

I tried a number of things using base apply and dplyr::rowwise but nothing worked quite right. In the docs for purrr::pmap I thought I found the answer:

f.   A function, formula, or vector (not necessarily atomic)...

If character vector, numeric vector, or list, it is converted to an extractor function. Character vectors index by name...

So I thought, great this should work: pmap(df, c("col_a", "col_b")) and that should extract those columns for each element (row) and return a list of the extracted lists. But when I run that I get:

 Error in pluck(x, "col_a", "col_b", .default = NULL) : 
  argument "x" is missing, with no default 

I semi-understand this error, but I think I'm following the usage in the docs. Maybe this is just a bug in purrr?

Anyway, commentary on the potential purrr bug is welcome, but really I'm just trying to create this list. Any help is very appreciated.

like image 978
seth127 Avatar asked Jul 24 '20 14:07

seth127


People also ask

Is a Tibble a list in R?

Tibbles are actually lists. Every tibble is a named list of vectors, each of the same length.

Is it possible to have a list as a column of a Tibble?

Tibbles can also have columns that are lists. These columns are (appropriately) called list columns. List columns are more flexible than normal, atomic vector columns.

How do I print all rows in a Tibble in R?

Use options(pillar. width = Inf) to always print all columns, regardless of the width of the screen. This will change the default behavior for all tibbles.


1 Answers

You can use group_split() (or base split() if you prefer):

library(dplyr)
library(purrr)

df %>%
  group_split(row_number(), .keep = FALSE) %>%
  map(as.list)

Where str() gives:

List of 3
 $ :List of 2
  ..$ col_a: num 1
  ..$ col_b: chr "A"
 $ :List of 2
  ..$ col_a: num 2
  ..$ col_b: chr "B"
 $ :List of 2
  ..$ col_a: num 3
  ..$ col_b: chr "C"

Or:

lapply(split(df, 1:nrow(df)),
       as.list)
like image 168
Ritchie Sacramento Avatar answered Sep 19 '22 22:09

Ritchie Sacramento