Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using purrr::pmap within mutate to create list-column

Tags:

r

dplyr

purrr

I understand how to use map to iterate over arguments in a df and create a new list column.

For example,

params <- expand.grid(param_a = c(2, 4, 6)
                  ,param_b = c(3, 6, 9)
                  ,param_c = c(50, 100)
                  ,param_d = c(1, 0)
                  )

df.preprocessed <- dplyr::as.tbl(params) %>%
  dplyr::mutate(test_var = purrr::map(param_a, function(x){
      rep(5, x)
      }
    ))

However, how do I use the analogous syntax with pmap in the event that I want to specify more than 2 parameters?

df.preprocessed <- dplyr::as.tbl(params) %>%
  dplyr::mutate(test_var = purrr::pmap(list(x = param_a
                                     ,y = param_b
                                     ,z = param_c
                                     ,u = param_d), function(x, y){
                                        rep(5,x)*y
                                     }
  )
  )

Error output:

Error in mutate_impl(.data, dots) : Evaluation error: unused arguments (z = .l[[c(3, i)]], u = .l[[c(4, i)]]).

like image 782
matsuo_basho Avatar asked Oct 02 '17 18:10

matsuo_basho


Video Answer


2 Answers

With pmap, the first argument is a list, so you can pass it your data frame directly, and then name your arguments in your function with the same names as the columns in your data frame. You'll need unnest() to unpack the list elements returned by pmap():

df.preprocessed <- dplyr::as.tbl(params) %>%
    dplyr::mutate(test_var = purrr::pmap(., function(param_a, param_b, ...){
                                        rep(5, param_a) * param_b
                                     })) %>%
    tidyr::unnest()


> df.preprocessed
# A tibble: 144 x 5
   param_a param_b param_c param_d test_var
     <dbl>   <dbl>   <dbl>   <dbl>    <dbl>
 1       2       3      50       1       15
 2       2       3      50       1       15
 3       4       3      50       1       15
 4       4       3      50       1       15
 5       4       3      50       1       15
 6       4       3      50       1       15
 7       6       3      50       1       15
 8       6       3      50       1       15
 9       6       3      50       1       15
10       6       3      50       1       15
# ... with 134 more rows
like image 183
sinQueso Avatar answered Oct 21 '22 06:10

sinQueso


How about using rowwise and mutate directly without map:

my_fun <- function(param_a, param_b){
  rep(5, param_a) * param_b
}
df.preprocessed <- dplyr::as.tbl(params) %>%
  rowwise() %>% 
  dplyr::mutate(test_var = list(my_fun(param_a, param_b))) %>% 
  tidyr::unnest()
like image 38
danilinares Avatar answered Oct 21 '22 06:10

danilinares