Passing a data frame to change a function

I would like to pass a data frame and its columns for processing dplyr mutate inside 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 an error

Error in mutate_impl object (.data, named_dots (...), environment ()) 'gear' not found

This is a problem with the environment in which dplyr mutate looks for the appropriate variable.

I understand it

 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 to avoid having to refer to every variable used from the data frame in the function call.

I also know that removing a mutation from a function call works without a problem. Namely, mutate(mtcars,newvar=gear*2) does its job. However, I am trying to understand how dplyr mutate looks for the right variable in different environments when placed inside a function.

+6
source share
4 answers

Considering @Anandas solution, this seems to be the easiest hack

 multifun <- function(dataf, vari){ dataf <- mutate(dataf, newvar = dataf[, vari]*2); return(dataf) } multifun(mtcars,"gear") 

Again, by accepting @Anandas offer, you can also do

 multifun <- function(dataf, vari){ vari <- deparse(substitute(vari)) dataf <- mutate(dataf, newvar = dataf[, vari]*2) return(dataf) } multifun(mtcars, gear) 
+4
source

This is really ugly for me, but it seems to work. Basically, I tried using get , but it didn't seem to know where to look, so I pointed out 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 
+4
source

or

 multifun1 <- function(dataf, vari){ eval(substitute(mutate(dataf, newvar=vari*2), list(vari=as.name(vari)))) } multifun1(mtcars,"gear") 

To use the unquoted value, it would be better to use the @Ananda Mahto clause

 multifun1 <- function(dataf, vari){ vari <- deparse(substitute(vari)) eval(substitute(mutate(dataf, newvar=vari*2), list(vari=as.name(vari)))) } multifun1(mtcars,gear) 
+2
source

With dplyr 0.7.0 this can now be done with tidyeval:

 multifun <- function(dataf,vari){ mutate(dataf,newvar = UQ(enquo(vari))*2) } multifun(mtcars,gear) 

enquo quotes a character referring to a function argument and associates it with the environment in which the function is called in quosure. UQ or !! can then be used to rule out quosure and immediately evaluate it within mutate .

+1
source

Source: https://habr.com/ru/post/971855/


All Articles