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

男娘i 2022-08-22 03:58 83阅读 0赞

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

  1. library(dplyr)
  2. mtcars %>% mutate(new_column = mpg + wt)

Here, dplyr uses non-standard evaluation in finding the contents for mpg and wt, knowing that it needs to look in the context ofmtcars. This is nice for interactive use, but not so nice for usingmutate 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 mtcarsyou 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:

  1. f = function(col1, col2, new_col_name) {
  2. mtcars %>% mutate(new_col_name = col1 + col2)
  3. }

The problem is that col1 and col2 are not interpreted, in steaddplyr 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:

  1. library(lazyeval)
  2. f = function(col1, col2, new_col_name) {
  3. mutate_call = lazyeval::interp(~ a + b, a = as.name(col1), b = as.name(col2))
  4. mtcars %>% mutate_(.dots = setNames(list(mutate_call), new_col_name))
  5. }
  6. head(f('wt', 'mpg', 'hahaaa'))
  7. mpg cyl disp hp drat wt qsec vs am gear carb hahaaa
  8. 1 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 23.620
  9. 2 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 23.875
  10. 3 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 25.120
  11. 4 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1 24.615
  12. 5 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2 22.140
  13. 6 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1 21.560

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.

发表评论

表情:
评论列表 (有 0 条评论,83人围观)

还没有评论,来说两句吧...

相关阅读