5
votes

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.

3

3 Answers

5
votes

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)
4
votes

You can use asplit().

type.convert(lapply(asplit(df, 1), as.list), as.is = T)

or by()

`attributes<-`(by(df, 1:nrow(df), as.list), NULL)

Both of str() give

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

We can use pmap

library(purrr)
dflist <- df %>%
              pmap(~ list(...))
str(dflist)
#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"