How to pass an expression "from higher level" to mutate?

486 Views Asked by At

I would like to create a higher level function that wrap a mutate. I want to give an expression parameter to my function and being able to use this expression in mutate :

datas <- data.frame(x = sample(100))
fn <- function(datas, expr) {
   mutate(datas, flag = eval(substitute(expr), datas))
}

fn(datas[1], x > 50)
Error in mutate_impl(.data, dots) : object 'x' not found 

But I don't understand why it fails since mutate(datas, flag = eval(substitute(x > 50), datas)) works.

What am I doing wrong ?

Thanks

2

There are 2 best solutions below

0
On BEST ANSWER

Try this:

fn <- function(df, expr)
eval(substitute(mutate(df, expr), list(expr=substitute(expr))))

or (preferably) this:

fn <- function(df, expr)
mutate_(df, .dots= list(flag=substitute(expr)))
2
On

Your best bet is probably to use dplyr::mutate_ which is designed for this kind of scenario when non-standard evaluation is problematic within a function.

fn <- function(datas, expr) {
  expr <- substitute(expr)
  dplyr::mutate_(datas, flag = expr)
}

See http://adv-r.had.co.nz/Computing-on-the-language.html#calling-from-another-function and vignette("nse").

Updated 2018-06-21:

As pointed out by @danilinares, the preferred syntax for dplyr has changed since this question was first raised. With newer versions of dplyr, tidy evaluation and quosures are used. So the example here would be:

library(dplyr)
fn <- function(datas, expr) {
  expr <- enquo(expr)
  mutate(datas, flag = !!expr)
}

More info is available in the dplyr programming article