For a nested function such as
fun_parent <- function(var) {
fun_child <- function(x) {
x + var
}
return(fun_child)
}
How can I customize the content of the returned function fun_child based on the input var?
For example,
test <- fun_parent(var = "y")
print(test)
Desirable output:
function(x) {
x + y
}
<environment: xxxxxx>
Actual (undesirable) output:
function(x) {
x + var
}
<environment: 0x7f7f20126b70>
Any help would be greatly appreciated!
Edit: As you may have guessed, the question described above is a simplified version of the actual question I had. The comment by Dan Adams prompted me to redefine my question. Then I realized that it would be hard to explain what I was really looking for without providing some context. So here is another reproducible example, still greatly simplified from my actual question, but with extra information.
Say I want to apply a model to a group of datasets using purrr::map(), and to construct the model based on user input:
set.seed(1234)
df_demo <- data.frame(
x1 = rnorm(100),
x2 = rnorm(100),
x3 = rnorm(100),
y = rnorm(100),
sex = factor(rep(c("f", "m"), each = 50))
)
func <- function(var) {
mod <- function(data) {
lm(y ~ var, data = data) # var is supplied by users
}
output <- df_demo |>
dplyr::group_by(group) |>
tidyr::nest() |>
dplyr::mutate(
model = purrr::map(data, mod),
tidy = purrr::map(model, broom::tidy)
) |>
tidyr::unnest(tidy)
return(output)
}
test <- func(var = "x1")
I also tried a variation of the version above:
df_demo <- ...
func <- function(var) {
output <- df_demo |>
dplyr::group_by(group) |>
tidyr::nest() |>
dplyr::mutate(model = purrr::map(data,
function(data, ...) {
lm(y ~ var, data = data)
}),
tidy = purrr::map(model, broom::tidy)
) |>
tidyr::unnest(tidy)
return(output)
}
test <- func(var = "x1")
Both versions failed to achieve the result I wanted.
An error was returned instead.
At first I thought it was because the input var = "x1" could not be passed into fun or into the nested function mod. That's when I posted the original question at the beginning of this post.
After seeing Dan Adams' comment, I tried to approach the question differently. Instead of supplying var = "x1", I turned the entire formula into a parameter, like this:
# func <- function(var) {
func <- function(formula) {
output <- df_demo |>
dplyr::group_by(group) |>
tidyr::nest() |>
dplyr::mutate(model = purrr::map(data,
function(data, ...) {
# lm(y ~ var, data = data)
lm(formula, data = data)
}),
tidy = purrr::map(model, broom::tidy)
) |>
tidyr::unnest(tidy)
return(output)
}
# test <- func(var = "x1")
test <- func(formula = y ~ x1)
Lo & Behold, this worked!
> test
# A tibble: 4 × 8
# Groups: group [2]
group data model term estimate std.error statistic p.value
<fct> <list> <list> <chr> <dbl> <dbl> <dbl> <dbl>
1 f <tibble [50 × 6]> <lm> (Intercept) 0.0675 0.170 0.398 0.692
2 f <tibble [50 × 6]> <lm> x1 0.0763 0.160 0.477 0.636
3 m <tibble [50 × 6]> <lm> (Intercept) -0.106 0.124 -0.855 0.397
4 m <tibble [50 × 6]> <lm> x1 0.384 0.128 3.01 0.00419
This solution is not quite the same as the original one I had envisioned. However, it does seem more straightforward.
BTW, I am really overwhelmed (in a good way) by how quickly people responded to my original question with some brilliant ideas. I must admit that some of them seemed way over my head. Nevertheless, I am going to carefully review them and try my best to select one as the solution to my original question.