purrr: Hand over column names as parameter list to pmap()

589 Views Asked by At

I would like to use purr::pmap() to hand over column names as parameters to a function using those names in dplyr functions. Example:

library(purrr)
library(dplyr)

tib <- tibble(A1 = 0:9, A2 = 10:19, A3 = 20:29, 
              B1 = 30:39, B2 = 40:49, B3 = 50:59,
              C1 = 60:69, C2 = 70:79, C3 = 80:89)

select_three <- function(data, first, second, third) {
  
  result = data %>% 
    select({{first}}, {{second}}, {{third}})
  
  result
}

This works:

single_test <- select_three(tib, A1, A2, A3)
print(single_test)
# A tibble: 10 x 3
      A1    A2    A3
   <int> <int> <int>
 1     0    10    20
 2     1    11    21
 3     2    12    22
 4     3    13    23
 5     4    14    24
 6     5    15    25
 7     6    16    26
 8     7    17    27
 9     8    18    28
10     9    19    29

This doesn't:

params <- list(tib,
               c(A1, B1, C1),
               c(A2, B2, C2),
               c(A3, B3, C3))

pmap_test <- pmap_dfr(params, select_three)

Error: Element 1 of `.l` must have length 1 or 30, not 9
2

There are 2 best solutions below

0
On BEST ANSWER

I would suggest to pass character vectors instead.

library(purrr)
library(dplyr)

params <- list(c("A1", "B1", "C1"),
              c("A2", "B2", "C2"),
              c("A3", "B3", "C3"))

select_three <- function(data, first, second, third) {
  result = data %>% select(.data[[first]], .data[[second]], .data[[third]])
  result
}


pmap(params, ~select_three(tib, ..1, ..2, ..3))

Note that select works with character arguments so using data %>% select(first, second, third) would work here but if you are going to use this for something else other than select general way would be to use .data pronoun.

0
On

use

params <- list(tib,
               c("A1", "B1", "C1"),
               c("A2", "B2", "C2"),
               c("A3", "B3", "C3"))

pmap_test <- pmap(.l = params[2:4], select_three, data = tib)

[[1]]
# A tibble: 10 x 3
      A1    A2    A3
   <int> <int> <int>
 1     0    10    20
 2     1    11    21
 3     2    12    22
 4     3    13    23
 5     4    14    24
 6     5    15    25
 7     6    16    26
 8     7    17    27
 9     8    18    28
10     9    19    29

[[2]]
# A tibble: 10 x 3
      B1    B2    B3
   <int> <int> <int>
 1    30    40    50
 2    31    41    51
 3    32    42    52
 4    33    43    53
 5    34    44    54
 6    35    45    55
 7    36    46    56
 8    37    47    57
 9    38    48    58
10    39    49    59

[[3]]
# A tibble: 10 x 3
      C1    C2    C3
   <int> <int> <int>
 1    60    70    80
 2    61    71    81
 3    62    72    82
 4    63    73    83
 5    64    74    84
 6    65    75    85
 7    66    76    86
 8    67    77    87
 9    68    78    88
10    69    79    89