Search code examples
rlazy-evaluationpurrrnse

Wrapping function around purrr::pmap using column names


I try to write a simple function wrapping around the purrr::pmap_dbl() function.

I have the following data:

df <- data.frame(
          col1 = 1:5, 
          col2 = 2:6, 
          col3 = 3:7
)

And the following function:

addfn <- function(x, y){
   x^2 + y
}

Then I would like to write a function like:

testfn <- function(data, a, b){
    purrr::pmap_dbl(data, function(a, b, ...) addfn(a, b))
}

Unfortunately, testfn(df, col1, col2) gives an error in this case. I would like to obtain the same output as the output obtained by:

purrr::pmap_dbl(df, function(col1, col2, ...) addfn(col1, col2))

What is the way to do this?


Solution

  • 1) testfn First, note that using testfn from the question that this already works:

    testfn(unname(df[c("col1", "col3")]))
    ## [1]  4  8 14 22 32
    

    2) testfn2 and we can modify that to:

    testfn2 <- function(data, ...) {
      data %>% select(...) %>% unname %>% purrr::pmap_dbl(addfn)
    }
    
    testfn2(df, col1, col3)
    ## [1]  4  8 14 22 32
    
    testfn2(df, "col1", "col3")
    ## [1]  4  8 14 22 32
    

    3) base R Of course as has been pointed out we don't really need purrr for this. This works in base R because addfn is vectorized:

    with(df, addfn(col1, col3))
    ## [1]  4  8 14 22 32
    

    or if addfn were not vectorized then:

    with(df, mapply(addfn, col1, col3))
    ## [1]  4  8 14 22 32
    

    and we could write this function using standard evaluation:

    testfn3 <- function(data, a, b) mapply(addfn, df[[a]], df[[b]])
    
    testfn3(df, "col1", "col3")
    ## [1]  4  8 14 22 32
    

    or using non-standard evaluation:

    testfn4 <- function(data, ...) eval.parent(substitute(
      with(data, mapply(addfn, ...))
    ))
    
    testfn4(df, col1, col3)
    ## [1]  4  8 14 22 32