2

I have a function that I want to wrap another function around, passing the arguments through as the ... arguments parameters. I'm having trouble learning how to structure the underlying function call with lazyeval Here's a decent MWE,

library(dplyr)

pythag <- function(a, b){
  sqrt(a^2 + b^2)
}
pythag_wrapper <- function(data, ...){
  dplyr::mutate_(data,
    root = lazyeval::interp(~pythag(x), x = ...)
  )
}

In this my pythag_wrapper will do some additional data munging. and pythag in my case has many more than two arguments. The function works just fine, and as intended.

test_data <- dplyr::data_frame(a = runif(10), b = runif(10), c = runif(10)) 

test_data %>%
  dplyr::mutate(
    root = pythag(a = b, b = c)
  )
## # A tibble: 10 × 4
##             a          b         c      root
##         <dbl>      <dbl>     <dbl>     <dbl>
## 1  0.19805337 0.05567241 0.9956758 0.9972311
## 2  0.22642799 0.18871552 0.8690659 0.8893195
## 3  0.09352032 0.57328658 0.7475573 0.9420719
## 4  0.40589832 0.71270806 0.8014196 1.0724860
## 5  0.35896302 0.85889027 0.8197176 1.1872782
## 6  0.66409819 0.02206298 0.1304790 0.1323312
## 7  0.45102742 0.76048535 0.5501899 0.9386410
## 8  0.48249177 0.93670363 0.8280114 1.2502066
## 9  0.05545819 0.12281684 0.9219704 0.9301148
## 10 0.47588862 0.40196106 0.0192433 0.4024214

I've tried all sorts of combinations of lazyeval::interp, lazy_eval::lazy_dots, etc., but I can't understand what exactly is supposed to happen, much less how to solve my problem.

pythag_wrapper(test_data, a = "a", b = "b")

## Error: object 'x' not found 
gregmacfarlane
  • 2,121
  • 3
  • 24
  • 53

1 Answers1

1

The problem in your code is on how you deal with the dots argument ....

Slightly changing your code and 'manually' rewriting the formula inside the wrapper it works fine:

pythag_wrapper <- function(data, ...){
   # From ... argument get names and values
   dots = list(...)

   # 'Write' the formula: ' ~ pythag(a = val1, b = val2)'
   yourformula = as.formula(
      paste0(" ~ pythag(", 
         paste0(names(dots), " = ", unlist(dots), collapse = ", "),
         ")")
       )

   # Apply the mutate_. The setNames here is what you need to 
      # apply the right name to the resulting column
   dplyr::mutate_(data, .dots = setNames(list(yourformula), 'root'))
}
Lorenzo Rossi
  • 1,481
  • 1
  • 9
  • 16
  • This gets me a little further (and solves the MWE), but my real case returns `Error in UseMethod("as.lazy_dots") : no applicable method for 'as.lazy_dots' applied to an object of class "function"`, which is still pretty obtuse. – gregmacfarlane Mar 10 '17 at 16:04
  • And can you explain why you tried to rewrite the function call? Is this the cleanest way to go after this kind of problem? – gregmacfarlane Mar 10 '17 at 16:05