R: Pass a List of Filtering Conditions into a Dataframe

R: pass a list of filtering conditions into a dataframe

Base R version:

conditions <- with(dat, list(Symbol %in% "ABM", Growth > 1.2, Yield > 2, Yield < 3, PE > 3))
dat[Reduce(`&`, conditions ),]
# Symbol Yield PE Growth
#2 ABM 2.24 21.18 3.33

R: pass a list of filtering conditions into a dataframe

Base R version:

conditions <- with(dat, list(Symbol %in% "ABM", Growth > 1.2, Yield > 2, Yield < 3, PE > 3))
dat[Reduce(`&`, conditions ),]
# Symbol Yield PE Growth
#2 ABM 2.24 21.18 3.33

R: how to pass a list of filters to a function

data.table way, with eval(parse())

library(data.table)
mt_dt <- data.table(mtcars)

filters <- c("mpg > 15", "wt < 2", "carb > 2 & am==0")

out <- sapply(filters, function(x){mt_dt[eval(parse(text = x)), mean(disp)]})
out
# mpg > 15 wt < 2 carb > 2 & am==0
# 192.3115 80.2250 324.4600

We are looping over our filters, and for each filter we subset and apply our aggregation function

This results in a named vector, which is quite flexible to work with. If you prefer a table, you can use:

data.table(subset = names(out), `mean(disp)` = out)
# subset mean(disp)
# 1: mpg > 15 192.3115
# 2: wt < 2 80.2250
# 3: carb > 2 & am==0 324.4600

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

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)

Filter each column with a different condition

You need some sort of object to specify whether to use < or >. I've created one called less, which is 1 for < and 0 for >.

require(purrr); require(magrittr)
filter2 <- function(dframe, cond, less){
rows <- pmap(list(cond, less, dframe),
function(cond, less, x) if(less) x < cond else x > cond
) %>%
pmap_lgl(all)
dframe[rows,]
}

dframe %>% filter2(cond = c(2, 1, -1.4), less = c(1, 1, 0))

Or, explicitly pass the function you want to use for each variable.

filter3 <- function(df, y, fun){
df[pmap(list(df, y, fun), function(x, y, fun) fun(x, y)) %>%
pmap_lgl(all)
,]
}

dframe %>% filter3(y = c(2, 1, -1.4), fun = list(`<`, `<`, `>`))

R how to automate a filter for unknown variables

You could use if_any and cur_column

library(dplyr)

df %>%
filter(
(if_all(
.cols = names(f_list),
.fns = ~ .x %in% f_list[[cur_column()]])
)
)

# V1 V2 V3
#1 1 B 100
#2 1 A 101
#3 1 A 102
#4 1 A 103

Note for the time being the () around if_all due to cur_column() requires extra parentheses to work inside if_any() and if_all()

Converting a quoted list into a list of quoted expressions for dplyr::filter

The problem is that, with the way you're using it, enexpr also captures the call to list,
whereas using the ellipsis already separates each expression into different elements of a list:

library(rlang)

foo <- function(x) {
enexpr(x)
}

foo(list(a, b, c))
# list(a, b, c)

bar <- function(...) {
enexprs(...)
}

bar(a, b, c)
# [[1]]
# a
#
# [[2]]
# b
#
# [[3]]
# c

To do what you want, you can use call_args to extract each expression from what was given to list:

baz <- function(x) {
as_expr <- enexpr(x)
# expr just to show
expr(filter(!!!call_args(as_expr)))
}

baz(list(a == 1, b < 2))
# filter(a == 1, b < 2)


Related Topics



Leave a reply



Submit