Search code examples
rfunctiondplyrscopingnse

Dplyr non standard evaluation with function name passed as a string


While working with dplyr pipeline, I would like to pass a function to mutate using NSE with the function name being passed from a vector.

Example

Given vector of two function names:

funs <- c("sum", "mean")

I would like to use first value to obtain sum:

require(dplyr)
mtcars %>% 
  group_by(cyl) %>% 
  mutate_(res = funs[1](hp))

This results in an error:

Error in as.lazy_dots(list(...)) : attempt to apply non-function

do.call

do.call based solution seems to generate some results for sum:

mtcars %>% 
  group_by(cyl) %>% 
  mutate_(res = do.call(funs[1], .))

but it fails when trying to use mean:

>> mtcars %>% 
+   group_by(cyl) %>% 
+   mutate_(res = do.call(funs[2], .))
Error in mean.default(mpg = c(21, 21, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4,  : 
  argument "x" is missing, with no default

I'm guessing that it simply makes no sense in the way it is applied here. Hence my question: how to use in dplyr so the function can be passed as a string from a vector?


Solution

  • We can use get and get extracts the values of a single string. Here, it is a function, so it returns the function itself.

    mtcars %>% 
         group_by(cyl) %>% 
         mutate(res= get(funs[1])(hp))
    

    For passing additional arguments

    mtcars$hp[1] <- NA
    mtcars %>%
          group_by(cyl) %>% 
          mutate(res= get(funs[1])(hp, na.rm = TRUE))