Search code examples
rpipelinepurrr

Using purrr::pmap with R's native pipe operator


One use of pmap is to deal with situations where one might want map3, but such a function does not exist in purrr. For example:

library(tidyverse)

Z <- tibble(x = list(sample(10, size = 2), sample(10, size = 3)), 
            fn = c(max, min)) 


Z %>% 
  mutate(msg2 = map2_chr(x, fn, \(x,fn) paste(toString(x), '->', fn(x))), # for 2 args this is the way
         msgp = pmap_chr(., \(x, fn) paste(toString(x), '->', fn(x))) # but can also do this
  )

(where my examples maps a function of two parameters, so I can actually use map2; but think of the analogous problem with three parameters).

I would like to update my code to use the new native R pipe |>, but the following does not work:

Z |> 
  mutate(msg2 = map2_chr(x, fn, \(x,fn) paste(toString(x), '->', fn(x))), # for 2 args this is the way
         msgp = pmap_chr(_, \(x, fn) paste(toString(x), '->', fn(x))) # but this is an ERROR
  )

What are some options for using pmap with mutate and with R's native pipe operator? Or, is this one situation where it makes sense to stick to using magritte's pipe (%>%)?


Solution

  • It may be better to use with ..1, ..2 as arguments. In the pmap code, the . will take the full dataset columns including the msg2 created (thus it is 3 columns instead of 2), but the lambda created had only two arguments

    library(dplyr)
    library(purrr)
    Z  |> 
      mutate(msg2 = map2_chr(x, fn, \(x,fn)
        paste(toString(x), '->', fn(x))),
       msgp = pmap_chr(across(everything()),
        ~ paste(toString(..1), "->", match.fun(..2)(..1))))
    

    -output

    # A tibble: 2 × 4
      x         fn     msg2         msgp        
      <list>    <list> <chr>        <chr>       
    1 <int [2]> <fn>   9, 3 -> 9    9, 3 -> 9   
    2 <int [3]> <fn>   6, 2, 9 -> 2 6, 2, 9 -> 2
    

    Or if make use of the OP's code and make slight modification to include only the x, fn columns

    Z |> 
      mutate(msg2 = map2_chr(x, fn, \(x,fn) 
        paste(toString(x), '->', fn(x))), # for 2 args this is the way
             msgp = pmap_chr(across(c(x, fn)),
        \(x, fn) paste(toString(x), '->', fn(x))) # but this is not an ERROR now
      )
    

    -output

    # A tibble: 2 × 4
      x         fn     msg2         msgp        
      <list>    <list> <chr>        <chr>       
    1 <int [2]> <fn>   9, 3 -> 9    9, 3 -> 9   
    2 <int [3]> <fn>   6, 2, 9 -> 2 6, 2, 9 -> 2