Reputation: 18585
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.
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 nse in dplyr
so the function can be passed as a string from a vector?
Upvotes: 3
Views: 167
Reputation: 269556
These both work using mutate
rather than mutate_
mtcars %>%
group_by(cyl) %>%
mutate(res = do.call(funs[2], list(hp)))
mtcars %>%
group_by(cyl) %>%
mutate(res = match.fun(funs[2])(hp))
Also note that if we use [[2]] in place of [2] then these will work with both the character vector, funs
, that appears in the question as well as funs <- c(sum, mean)
.
Upvotes: 2
Reputation: 887108
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))
Upvotes: 3