Search code examples
rdplyrnse

Using strings as arguments in custom dplyr function using non-standard evaluation


I'm trying to write a function that takes a metric and computes relative difference from the first value of that metric with dplyr functions and non-standard evaluation. Following these instructions (https://cran.r-project.org/web/packages/dplyr/vignettes/programming.html), I've come up with this, which works well:

testFun <- function(data, metric) {
  metric <- enquo(metric)
  metric_name <- quo_name(metric)
  data %>%
    mutate(!!metric_name := `-`(!!metric, first(!!metric)) / first(!!metric) * 
100)
}

testFun(data.frame(x = c("a", "b", "c"), y = 1:3), y)

However, the problem is that elsewhere in the code I have other functions that take the metric name as a string stored in some variable, for example:

myVar <- "y"

I wouldn't want to change everything, but I'd still like to use the same variables. So my question is, can I make the same function work with this call?

testFun(data.frame(x = c("a", "b", "c"), y = 1:3), myVar)

Either by changing something in the function or adapting the input in the call somehow. The latter would be preferable. I've tried various quoting, unquoting, evaluation etc. of myVar, but I don't really understand all of this that well and couldn't come up with a working solution. The way I understand it, I somehow need to get ~y from myVar. Can it be done?


Solution

  • You can either use sym to turn "y" into a symbol or parse_expr to parse it into an expression, then unquote it using !!:

    library(rlang)
    
    testFun(data.frame(x = c("a", "b", "c"), y = 1:3), !!sym(myVar))
    
    testFun(data.frame(x = c("a", "b", "c"), y = 1:3), !!parse_expr(myVar))
    

    Result:

      x   y
    1 a   0
    2 b 100
    3 c 200
    

    Check my answer in this question for explanation of difference between sym and parse_expr.