Reputation: 1928
I'm attempting to use non-standard evaluation with a function where one set of things happen if one column is present in the supplied data.frame and something else happens if a different column is present. I don't know how to check that condition, though, when the user supplies the column names in the function. Here's an example:
DF1 <- tibble(ColA = 1:4, ColB = 9:12)
DF2 <- tibble(ColA = 1:4, ColC = 5:8)
If columnB existed in all data.frames the user might supply, then this function would work:
myfun1 <- function(DF, columnA, columnB){
columnA <- enquo(columnA)
columnB <- enquo(columnB)
DF %>% mutate(NewColumn = !!columnA * !!columnB)
}
myfun1(DF1, columnA = ColA, columnB = ColB)
And if columnC always existed, then this function would work:
myfun2 <- function(DF, columnA, columnC){
columnA <- enquo(columnA)
columnC <- enquo(columnC)
DF %>% mutate(NewColumn = !!columnA / !!columnC)
}
myfun2(DF2, columnA = ColA, columnC = ColC)
But what I really want is a more flexible function that will check whether columnB is a column in the supplied data.frame, do something if it is, and if it isn't, do something else. Something like this except that I know the if
statement is incorrect:
myFlexibleFun <- function(DF, columnA, columnB, columnC){
columnA <- enquo(columnA)
columnB <- enquo(columnB)
columnC <- enquo(columnC)
if(exists(!!columnB)){ # I know "exists" isn't the correct syntax, but what is?
DF %>% mutate(NewColumn = !!columnA * !!columnB)
} else {
DF %>% mutate(NewColumn = !!columnA / !!columnC)
}
}
I tried if(quote(columnB) %in% names(DF))
and I tried if(deparse(columnB) %in% names(DF))
and those didn't work.
I'd like it if
myFlexibleFun(DF1, columnA = ColA, columnB = ColB)
and also
myFlexibleFun(DF2, columnA = ColA, columnC = ColC)
both worked.
Upvotes: 1
Views: 69
Reputation: 5956
quote()
isn't working because you've already converted columnB
to be a quosore, so you need to use as_label()
instead.
myFlexibleFun <- function(DF, columnA, columnB, columnC){
columnA <- enquo(columnA)
columnB <- enquo(columnB)
columnC <- enquo(columnC)
if(as_label(columnB) %in% names(DF)){
DF %>% mutate(NewColumn = !!columnA * !!columnB)
} else {
DF %>% mutate(NewColumn = !!columnA / !!columnC)
}
}
This lets you get what you want:
myFlexibleFun(DF1, columnA = ColA, columnB = ColB)
#> # A tibble: 4 x 3
#> ColA ColB NewColumn
#> <int> <int> <int>
#> 1 1 9 9
#> 2 2 10 20
#> 3 3 11 33
#> 4 4 12 48
myFlexibleFun(DF2, columnA = ColA, columnC = ColC)
#> # A tibble: 4 x 3
#> ColA ColC NewColumn
#> <int> <int> <dbl>
#> 1 1 5 0.2
#> 2 2 6 0.333
#> 3 3 7 0.429
#> 4 4 8 0.5
Upvotes: 2