I would like to pass a data frame and its columns to be processed by dplyr's mutate within a function.
Here is an example
multifun <- function(dataf,vari){
mutate(dataf,newvar=vari*2)
}
multifun(mtcars,gear)
The problem with this function is that the variable 'gear' is not a recognized object. More specifically I get the error
Error in mutate_impl(.data, named_dots(...), environment()) object 'gear' not found
This is a problem with the environment where dplyr's mutate is looking for the variable in question.
I understand that
multifun(mtcars,mtcars$gear)
will give me the answer that I want, namely
mpg cyl disp hp drat wt qsec vs am gear carb newvar
1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 8
2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 8
3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 8
but I would like to see if there is a way of avoiding the need to reference each variable used from the data frame in the function call.
I am also aware that taking mutate out of the function call works without problems. Namely, mutate(mtcars,newvar=gear*2)
does the job. However, I am trying to understand how dplyr's mutate is looking for the variable in question in the different environments when placed inside a function.
Looking at @Anandas solution, this seems to be simplest hack
multifun <- function(dataf, vari){
dataf <- mutate(dataf, newvar = dataf[, vari]*2);
return(dataf)
}
multifun(mtcars,"gear")
Again, taking incount @Anandas suggestion, you could also do
multifun <- function(dataf, vari){
vari <- deparse(substitute(vari))
dataf <- mutate(dataf, newvar = dataf[, vari]*2)
return(dataf)
}
multifun(mtcars, gear)
This is really ugly to me, but seems to work. Basically, I tried using get
but it didn't seem to know where to look, so I specified the environment.
multifun <- function(dataf, vari){
vari <- deparse(substitute(vari))
mutate(dataf, newvar = get(vari, envir = as.environment(dataf)) * 2)
}
Output:
multifun(mtcars, gear)
# mpg cyl disp hp drat wt qsec vs am gear carb newvar
# Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 8
# Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 8
# Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 8
# <<<SNIP>>>
# Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 10
# Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8 10
# Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 8
Or
multifun1 <- function(dataf, vari){
eval(substitute(mutate(dataf, newvar=vari*2), list(vari=as.name(vari))))
}
multifun1(mtcars,"gear")
To use unquoted
value, it would be better to use @Ananda Mahto's suggestion
multifun1 <- function(dataf, vari){
vari <- deparse(substitute(vari))
eval(substitute(mutate(dataf, newvar=vari*2), list(vari=as.name(vari))))
}
multifun1(mtcars,gear)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With