Using mutate from dplyr inside a function: getting around non-standard evaluation

To edit or add columns to a data.frame, you can use mutate from the dplyr package:

Here, dplyr uses non-standard evaluation in finding the contents for mpg and wt, knowing that it needs to look in the context of mtcars. This is nice for interactive use, but not so nice for using mutate inside a function where mpg and wt are inputs to the function.

The goal is to write a function f that takes the columns in mtcars you want to add up as strings, and executes mutate. Note that we also want to be able to set the new column name. A first naive approach might be:

The problem is that col1 and col2 are not interpreted, in stead dplyr tries looking for col1 and col2 in mtcars. In addition, the name of the new column will be new_col_name, and not the content of new_col_name. To get around non-standard evaluation, you can use the lazyeval package. The following function does what we expect:

The important parts here are, given the call to f above:

  • lazyeval::interp(~ a + b, a = as.name(col1), b = as.name(col2)) this creates the expression wt + mpg.
  • mutate_(mutate_call) where mutate_ is the version of mutate that uses standard evaluation (SE).
  • setNames(list(mutate_call), new_col_name)) sets the output name to the content of new_col_name, i.e. hahaaa.
Tagged with: ,
Posted in R stuff
11 Comments » for Using mutate from dplyr inside a function: getting around non-standard evaluation
  1. Dimitris says:

    Or you could evaluate the text constract of ‘mtcars %>% …’ like so:

  2. Arun says:

    Hi, could you also show how to go about if you’ve, say, 10 (or 100) columns to get the sum of, and I pass all the col names as a character vector in 1 argument? Thank you.

    • Paul Hiemstra says:

      The trick is to create a list of calls to interp:

      • Arun says:

        Apologies I did not explain myself well. Suppose we’ve

        I’d like to have

        Instead of x,y,z, let’s say we’ve 100 cols. In other words, I was asking for an extension of the case you’ve shown – from two columns to >10 or 100 cols.

        • Paul Hiemstra says:

          I’d do something like:

  3. Vincent says:

    Hi. Why do you dont use the mutate_ fonction with the dot parameter ?

  4. myschizobuddy says:

    So it goes from being beautiful to a total nuisance. Time to move to data.table

  5. myschizobuddy says:

    If mutate cannot find col1 inside mtcars then perhaps there should be another parameter that tells mutate Hey look at whats inside col1 and then find that in mtcars. Instead we have this complete mess

1 Pings/Trackbacks for "Using mutate from dplyr inside a function: getting around non-standard evaluation"
  1. […] Using mutate from dplyr inside a function: getting around non-standard evaluation […]

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

*