I am learning about programming with tidy
evaluation and non-standard evaluation and have been trying to work out how to constrain the possible states of an argument in a function.
For instance given a data set:
set.seed(123)
data <- data_frame(GROUP_ONE = sample(LETTERS[1:3], 10, replace = TRUE),
GROUP_TWO = sample(letters[4:6], 10, replace = TRUE),
result = rnorm(10))
I can create a function which has an argument I use to group the data using a quosure like so:
my_function <- function(data, group = GROUP_ONE){
require(dplyr)
require(magrittr)
group <- enquo(group)
result <- data %>%
group_by(!!group) %>%
summarise(mean=mean(result))
return(result)
}
and this does what I want
my_function(data)
# A tibble: 3 x 2
GROUP_ONE mean
<chr> <dbl>
1 A 1.5054975
2 B 0.2817966
3 C -0.5129904
and I can supply a different group:
my_function(data, group = GROUP_TWO)
# A tibble: 3 x 2
GROUP_TWO mean
<chr> <dbl>
1 d -0.3308130
2 e 0.2352483
3 f 0.7347437
However, I cannot group by a column for which is not present in the data.
e.g.
my_function(data, group = GROUP_THREE)
Error in grouped_df_impl(data, unname(vars), drop) : Column
GROUP_THREE
is unknown
I would like to add a step at the beginning of the function so that the function stops with a custom error message if the group argument is not GROUP_ONE or GROUP_TWO
something like:
if(!group %in% c(~GROUP_ONE, ~GROUP_TWO)) stop("CUSTOM ERROR MESSAGE")
except this does not work as you apparently you can't put quosures in a vector. It should be possible to convert the quosure to a string somehow and have a vector of strings but I can't figure out how.
How is this done?
I think you need quo_name
(from dplyr
or rlang
), which transforms a quoted symbol to a string:
my_function <- function(data, group = GROUP_ONE){
require(dplyr)
require(magrittr)
group <- enquo(group)
if(!quo_name(group) %in% names(data)) stop("CUSTOM ERROR MESSAGE")
result <- data %>%
group_by(!!group) %>%
summarise(mean=mean(result))
return(result)
}
# > my_function(data, GROUP_THREE)
# Error in my_function(data, GROUP_THREE) : CUSTOM ERROR MESSAGE
As noted by lionel in comment: except for quo_name
, there are many other alternatives including base R as.character
and as_string
from rlang
.