Using tidy evaluation to filter in my own function

177 views Asked by At

I am having a hard time to use tidy evaluation when writing my own function. I'll illustrate my problem using the ToothGrowth dataset, where we want to filter for e.g. VC as the supplement.

install.packages("tidyverse")
library(tidyverse)
data(ToothGrowth)

test <- function(df, condition) {
  df %>% filter(supp %in% condition)
}

test(ToothGrowth, "VC")

This returns the expected output, where the dataframe only contains VC as supp.
However, I do not want to quote all the arguments in my function, which is a bit more complex, and takes many more arguments. This is just to demonstrate the problem. Where i am stuck is, that dplyr::filter() requires quoted arguments. My solution was to use ensym(), so i could use VC instead of "VC".

test <- function(df, condition) {
  condition <- ensym(condition)

  df %>% filter(supp %in% condition)
}

test(ToothGrowth, VC)

Fehler: Problem with `filter()` input `..1`.
x 'match' benötigt Vektoren als Argumente
ℹ Input `..1` is `supp %in% condition`.

I've tried quo(), enquo(), sym(), ensym() so far, but can't get it to work..

Is there a way to supply an unquoted argument to my function and quote it within the function, so dplyr::filter() can use it?
Help is appreciated.

2

There are 2 answers

1
Ronak Shah On BEST ANSWER

You can use deparse + substitute to change unquoted arguments to quoted ones.

library(dplyr)

test <- function(df, condition) {
  val <- deparse(substitute(condition))
  df %>% filter(supp %in% val)
}

test(ToothGrowth, VC)
0
Lionel Henry On

VC is a value, not a variable. You can make the UI you're looking for if you really want to, but it would make your function very peculiar in feel. If you want to follow convention, keep data-masking for data frame columns.