Say I have this data:
d <- msleep %>%
mutate(comfort_color_desk = sample(c(0,1), replace=TRUE, size=nrow(msleep)),
comfort_color_chair = sample(c(0,1), replace=TRUE, size=nrow(msleep)))
I want to pass it through to a dplyr chain that lives inside a function i’ve made, which also includes an indicator to trigger an {if} clause inside of the chain.
For example (this works just fine):
test_fcn <- function(.x, .y, .count = NULL) {
.x %>% select(order, .y) %>%
{if(isTRUE(.count)) count(.,!!ensym(.y)) else .}
}
d %>% test_fcn(., .y = "comfort_color_desk", .count = TRUE)
This shows the basic principle of what I want to do. The problem i’m facing is when I want to just pass through a part of column name and paste that with a string and evaluate it as a data column inside the function.
For example (this does not work):
test_2_fcn <- function(.x, .y, .z, .compare = NULL) {
.x %>%
{if(isTRUE(.compare)) filter(., paste0("comfort_color_", !!ensym(.y)) == 1 & paste0("comfort_color", !!ensym(.z)) == 1) else .}
}
d %>% test_2_fcn(., .y = "desk", .z = "chair", .compare = TRUE)
I suspect this is a problem with tidy evaluation. Can anyone point in the right direction here please?
>Solution :
This is an issue of tidy evaluation. paste0 function is being evaluated before the !!ensym() is evaluated, now it is tried to paste the literal string "comfort_color_" with the symbol .y or .z instead of the values.
We could use the sym() function to convert the string to a symbol and then use paste() to concatenate the strings together.
library(dplyr)
test_2_fcn <- function(.x, .y, .z, .compare = NULL) {
.x %>%
{if(isTRUE(.compare)) filter(., !!sym(paste0("comfort_color_", .y)) == 1 & !!sym(paste0("comfort_color_", .z)) == 1) else .}
}
d %>% test_2_fcn(., .y = "desk", .z = "chair", .compare = TRUE)