I would like to pass the names of several variables to a function that is using tidyeval.
I know I can pass the vars
like this:
a_summary_fn <- function(the_data, the_group, vars) {
the_data |>
group_by({{the_group}}) |>
summarize(
across(
{{vars}},
list(
mean = ~mean(., na.rm = TRUE),
sd = ~sd(., na.rm = TRUE),
n = ~sum(!is.na(.))
)
)
) |>
mutate(across(ends_with(c("_mean", "_sd")), ~round(., digits = 3)))
}
a_summary_fn(mtcars, cyl, c(disp, hp))
but I was hoping to pass the analysis vars
like arguments. Is there a way to pass them into a function by capturing the dots and converting them to variable names using tidyeval?
Ideally I want something like this:
a_summary_fn <- function(the_data, the_group, ...) {
the_data |>
group_by({{the_group}}) |>
summarize(
across(
...,
list(
mean = ~mean(., na.rm = TRUE),
sd = ~sd(., na.rm = TRUE),
n = ~sum(!is.na(.))
)
)
) |>
mutate(across(ends_with(c("_mean", "_sd")), ~round(., digits = 3)))
}
a_summary_fn(mtcars, cyl, disp, hp)
You are close, just use c()
:
a_summary_fn <- function(the_data, the_group, ...) {
the_data |>
group_by({{the_group}}) |>
summarize(
across(
c(...),
list(
mean = ~mean(., na.rm = TRUE),
sd = ~sd(., na.rm = TRUE),
n = ~sum(!is.na(.))
)
)
) |>
mutate(across(ends_with(c("_mean", "_sd")), ~round(., digits = 3)))
}
a_summary_fn(mtcars, cyl, disp, hp)
If you were to write this out you would not do across(disp, hp, <function>)
, you would do across(c(disp, hp), <function>)
Output
cyl disp_mean disp_sd disp_n hp_mean hp_sd hp_n
<dbl> <dbl> <dbl> <int> <dbl> <dbl> <int>
1 4 105. 26.9 11 82.6 20.9 11
2 6 183. 41.6 7 122. 24.3 7
3 8 353. 67.8 14 209. 51.0 14