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?
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)