One area in R that I struggle with is specifying variable names in functions. I have seen examples and sometimes gotten them to work using {{argument}} or other approaches, but I don't really understand why some things work and others don't. For example, I just tried to make a function that would use 2 variable values to generate a new variable. Reproducible example below:
look<-cars
twotoone<-function(v1,v2,nv){
look<-look %>% mutate(nv=case_when(
v1 > 4 & v2 > 4 ~ 1,
TRUE ~ 0
))
look<<-look
}
twotoone(speed,dist,allover4)
I get an error:
Error: Problem with
mutate()
columnnv
. inv = case_when(v1 > 4 & v2 > 4 ~ 1, TRUE ~ 0)
. x object 'speed' not found
If I put all arguments in quotes:
twotoone('speed','dist','allover4')
there is no error, but the output data frame has the new variable nv instead of'allover4', and it's always =1 (no 0 assigned even when one of speed or distance are below 4). The same result happens if I just quote the first two arguments:
twotoone('speed','dist',allover4)
Any assistance to help me understand how I can expand the use of functions to help with recodes and composite variables, would be much appreciated. Thanks!!
CodePudding user response:
We may use {{}}
- curly-curly operator which does the non-standard evaluation of passing unquoted arguments - previously it was done with enquo
!!
. Generally, the =
cannot do evaluation of expression on the lhs whereas the :=
operator in tidyverse can do it and that is the reason we use :=
twotoone<-function(dat, v1,v2,nv){
dat %>%
mutate({{nv}} := case_when(
{{v1}} > 4 & {{v2}} > 4 ~ 1,
TRUE ~ 0
))
}
-testing
twotoone(cars, speed,dist,allover4)
speed dist allover4
1 4 2 0
2 4 10 0
3 7 4 0
4 7 22 1
5 8 16 1
6 9 10 1
...
CodePudding user response:
Here is the version with ensym
and !!
:
twotoone<-function(df, v1,v2,nv){
v1 <- rlang::ensym(v1)
v2 <- rlang::ensym(v2)
nv <- rlang::ensym(nv)
df %>%
mutate(!!nv := case_when(
!!v1 > 4 & !!v2 > 4 ~ 1,
TRUE ~ 0
))
}
twotoone(cars, speed,dist,allover4)
speed dist allover4
<dbl> <dbl> <dbl>
1 4 2 0
2 4 10 0
3 7 4 0
4 7 22 1
5 8 16 1
6 9 10 1
7 10 18 1
8 10 26 1
9 10 34 1
10 11 17 1
# ... with 40 more rows