How to filter a data frame programmatically with dplyr and tidy evaluation?

Viewed 1698

Let's say I want to filter the starwars data frame programmatically. Here's a simple example that lets me filter based on homeworld and species:

library(tidyverse)

# a function that allows the user to supply filters
filter_starwars <- function(filters) {
  for (filter in filters) {
    starwars = filter_at(starwars, filter$var, all_vars(. %in% filter$values))
  }

  return(starwars)
}

# filter Star Wars characters that are human, and from either Tatooine or Alderaan
filter_starwars(filters = list(
  list(var = "homeworld", values = c("Tatooine", "Alderaan")),
  list(var = "species", values = "Human")
))

But this doesn't let me specify, say, a height filter, because I've hard-coded the %in% operator in the .vars_predicate of filter_at(), and a height filter would use one of the >, >=, <, <=, or == operators

What is the best way to write the filter_starwars() function so that the user can supply filters that are general enough to filter along any column and use any operator?

NB using the now-deprecated filter_() method, I could pass a string:

filter_(starwars, "species == 'Human' & homeworld %in% c('Tatooine', 'Alderaan') & height > 175")

But again, that has been deprecated.

2 Answers
Related