I saw this idea on another question here.
I created a list of functions using rlang::enexprs()
. I want to apply this list on a data frame, so that I get a single frame with all the functions applied.
I have tried something like:
select.expr <- function(...) rlang::enexprs(...)
apply.expr <- function(df, filtre.list) {
eval_df <- function(df, expr) rlang::eval_tidy(expr, data = df)
purrr::reduce(filtre.list, eval_df, .init = df)
}
But it doesn’t work as I would like. For example:
data <- data.frame(a = c(1, 1, 1, 1),
b = c(2, 2, 2, 2),
c = c(3, 3, 3, 3))
expr <- select.expr(replace(data, data == 2, "two"),
replace(data, data == 3, "three"))
apply.expr(data, expr)
## a b c
## 1 1 2 three
## 2 1 2 three
## 3 1 2 three
## 4 1 2 three
This only works if I pass my data frame data
as an argument to eval_df
:
apply.expr <- function(df, filtre.list) {
eval_df <- function(data, expr) rlang::eval_tidy(expr, data = data)
purrr::reduce(filtre.list, eval_df, .init = df)
}
apply.expr(data, expr)
## a b c
## 1 1 two three
## 2 1 two three
## 3 1 two three
## 4 1 two three
But then I cannot use my function apply.expr()
with another data frame. I have also tried with map()
. Is there a way to create a function that applies a list of expressions to any date frame?
The issue is your expr
alters data
and in apply.expr()
you are changing df
. Therefore, we should change ```expr`` into:
expr <- select.expr(replace(df, df== 2, "two"),
replace(df, df== 3, "three"))
which works as expected:
apply.expr(data, expr)
a b c
1 1 two three
2 1 two three
3 1 two three
4 1 two three
and it works on another dataset:
data_alt <- data.frame(a = c(1, 1, 1, 1),
b = c(2, 2, 2, 2),
c = c(3, 3, 3, 3))
apply.expr(data_alt, expr)
a b c
1 1 two three
2 1 two three
3 1 two three
4 1 two three