schnee
schnee

Reputation: 1057

How to programmatically provide a list of filters to apply via dplyr and filter_

I'd like to create a list of filters to apply to a dataframe. Something like:

filters = list(cyl=4, am=1)

and then apply that to the 'mtcars' dataframe, to get just the records with cyl=4 and am=1. I can do this:

filter_(mtcars, 
        lazyeval::interp(~ val == var, val = as.name(names(filters[1])), 
                                       var = filters[[1]]))

But that only pick up the 1st entry in the filters list.

What is the idiomatic way to apply all of the filters?

(I'm trying to create a somewhat generic function that can accept a dataframe and a criteria set and will output transformations. Right now, equality is fine for the criteria, but more general idioms would be nice)

Upvotes: 6

Views: 941

Answers (3)

konvas
konvas

Reputation: 14346

All answers here are good but if you strictly want to keep your original way of defining the filter (via a list) you can simply convert it to a string an pass it to filter_ like

filter_(mtcars, paste(names(filters), filters, sep = "==", collapse = "&"))

(with the added benefit that this allows flexibility in terms of the logical operators you use, e.g. can change collapse to "|" etc)

Upvotes: 1

Amrita Sawant
Amrita Sawant

Reputation: 10913

    data <- mtcars
    attach(data)

    ##function to create data subset applying necessary filters
     myfunction <- function(myfilter){
     newdata <- data[myfilter,]
     print(newdata)
     }

     ##calling function
     myfunction(cyl==4 & am==1)
     myfunction(mpg >20 & gear > 1)


     Output
    > myfunction(cyl==4 & am==1)

                   mpg    cyl  disp   hp drat wt    qsec  vs am gear carb
    Datsun 710     22.8   4    108.0  93 3.85 2.320 18.61  1  1    4    1
    Fiat 128       32.4   4    78.7   66 4.08 2.200 19.47  1  1    4    1
    Honda Civic    30.4   4    75.7   52 4.93 1.615 18.52  1  1    4    2
    Toyota Corolla 33.9   4    71.1   65 4.22 1.835 19.90  1  1    4    1
    Fiat X1-9      27.3   4    79.0   66 4.08 1.935 18.90  1  1    4    1
    Porsche 914-2  26.0   4    120.3  91 4.43 2.140 16.70  0  1    5    2
    Lotus Europa   30.4   4    95.1   113 3.77 1.513 16.90 1  1    5    2
    Volvo 142E     21.4   4    121.0  109 4.11 2.780 18.60 1  1    4    2 

Upvotes: 1

bergant
bergant

Reputation: 7232

Define filter as

filter1 <- ~(cyl==4 & am==1)

or

filter1 <- "cyl==4 & am==1"

or

library(lazyeval)
filter1 <- lazy(cyl==4 & am==1)

and use as

mtcars %>% filter_(filter1)

Example with a function:

get_cars_with_filter <- function(my_filter) {
  mtcars %>% filter_(lazy(my_filter))
}

get_cars_with_filter(cyl==4 & am == 1)

Upvotes: 2

Related Questions