dplyr
dplyr copied to clipboard
How to adjust to different behavior of across .fn argument passing in dplyr 1.1.1 vs. 1.0.10?
I have a summarizing function that's similar to the function below. It allows the user to pass grouping variables, summary variables and any number of summary functions as arguments.
# Allow user to choose summary function(s)
fnc = function(data, summary.vars=NULL, group.vars=NULL,
FUNS=c(mean=~mean(., na.rm=TRUE))) {
data %>%
group_by(across({{group.vars}})) %>%
summarise(n=n(), across({{summary.vars}},
.fn=FUNS,
.names="{.col}_{.fn}"))
}
I often use weighted.mean
as a summary function in the FUNS
argument, which requires a weighting variable, which I pass with the bare column name, like this:
mtcars %>% fnc(c(mpg, hp), c(vs, am),
FUNS=c(mean=~mean(., na.rm=TRUE),
mean.wted=~weighted.mean(., w=cyl, na.rm=TRUE)))
This approach worked in dplyr 1.0.10
and previous versions, but is failing in dplyr 1.1.1
. Reproducible examples are below, first with 1.0.10 then with 1.1.1.
How can I update my function so that it will work properly with dplyr 1.1.1
? I've never been happy with hard-coding the w
argument anyway. Is there some tidyeval way that I should be passing the w
argument into the summary function?
Example with dplyr 1.0.10
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
# Allow user to choose summary function(s)
fnc = function(data, summary.vars=NULL, group.vars=NULL,
FUNS=c(mean=~mean(., na.rm=TRUE))) {
data %>%
group_by(across({{group.vars}})) %>%
summarise(n=n(), across({{summary.vars}},
.fn=FUNS,
.names="{.col}_{.fn}"))
}
# These work in both 1.0.10 and 1.1.1
mtcars %>% fnc(c(mpg, hp))
#> # A tibble: 1 × 3
#> n mpg_mean hp_mean
#> <int> <dbl> <dbl>
#> 1 32 20.1 147.
mtcars %>% fnc(c(mpg, hp), c(vs, am))
#> `summarise()` has grouped output by 'vs'. You can override using the `.groups`
#> argument.
#> # A tibble: 4 × 5
#> # Groups: vs [2]
#> vs am n mpg_mean hp_mean
#> <dbl> <dbl> <int> <dbl> <dbl>
#> 1 0 0 12 15.0 194.
#> 2 0 1 6 19.8 181.
#> 3 1 0 7 20.7 102.
#> 4 1 1 7 28.4 80.6
# Passing a weighting variable as the w argument in weighted.mean works in dplyr 1.0.10 but fails in dplyr 1.1.1
mtcars %>% fnc(c(mpg, hp), c(vs, am),
FUNS=c(mean=~mean(., na.rm=TRUE),
mean.wted=~weighted.mean(., w=cyl, na.rm=TRUE)))
#> `summarise()` has grouped output by 'vs'. You can override using the `.groups`
#> argument.
#> # A tibble: 4 × 7
#> # Groups: vs [2]
#> vs am n mpg_mean mpg_mean.wted hp_mean hp_mean.wted
#> <dbl> <dbl> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 0 0 12 15.0 15.1 194. 194.
#> 2 0 1 6 19.8 19.0 181. 198.
#> 3 1 0 7 20.7 20.4 102. 105.
#> 4 1 1 7 28.4 28.4 80.6 80.6
sessionInfo()
#> R version 4.2.2 (2022-10-31)
#> Platform: aarch64-apple-darwin20 (64-bit)
#> Running under: macOS Ventura 13.2.1
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRlapack.dylib
#>
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] dplyr_1.0.10
#>
#> loaded via a namespace (and not attached):
#> [1] rstudioapi_0.14 knitr_1.42 magrittr_2.0.3 tidyselect_1.2.0
#> [5] R.cache_0.16.0 R6_2.5.1 rlang_1.1.0.9000 fastmap_1.1.1
#> [9] fansi_1.0.4 styler_1.9.1 tools_4.2.2 xfun_0.37
#> [13] R.oo_1.25.0 utf8_1.2.3 DBI_1.1.3 cli_3.6.1
#> [17] withr_2.5.0 htmltools_0.5.4 yaml_2.3.7 digest_0.6.31
#> [21] tibble_3.2.1 lifecycle_1.0.3 purrr_1.0.1 vctrs_0.6.0.9000
#> [25] R.utils_2.12.2 fs_1.6.1 glue_1.6.2 evaluate_0.20
#> [29] rmarkdown_2.20 reprex_2.0.2 compiler_4.2.2 pillar_1.8.1
#> [33] generics_0.1.3 R.methodsS3_1.8.2 pkgconfig_2.0.3
Same example, but with dplyr 1.1.1
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
# Allow user to choose summary function(s)
fnc = function(data, summary.vars=NULL, group.vars=NULL,
FUNS=c(mean=~mean(., na.rm=TRUE))) {
data %>%
group_by(across({{group.vars}})) %>%
summarise(n=n(), across({{summary.vars}},
.fn=FUNS,
.names="{.col}_{.fn}"))
}
# These work in both 1.0.10 and 1.1.1
mtcars %>% fnc(c(mpg, hp))
#> # A tibble: 1 × 3
#> n mpg_mean hp_mean
#> <int> <dbl> <dbl>
#> 1 32 20.1 147.
mtcars %>% fnc(c(mpg, hp), c(vs, am))
#> `summarise()` has grouped output by 'vs'. You can override using the `.groups`
#> argument.
#> # A tibble: 4 × 5
#> # Groups: vs [2]
#> vs am n mpg_mean hp_mean
#> <dbl> <dbl> <int> <dbl> <dbl>
#> 1 0 0 12 15.0 194.
#> 2 0 1 6 19.8 181.
#> 3 1 0 7 20.7 102.
#> 4 1 1 7 28.4 80.6
# Passing a weighting variable as the w argument in weighted.mean works in dplyr 1.0.10 but fails in dplyr 1.1.1
mtcars %>% fnc(c(mpg, hp), c(vs, am),
FUNS=c(mean=~mean(., na.rm=TRUE),
mean.wted=~weighted.mean(., w=cyl, na.rm=TRUE)))
#> Error in `summarise()`:
#> ℹ In argument: `across(c(mpg, hp), .fn = FUNS, .names =
#> "{.col}_{.fn}")`.
#> ℹ In group 1: `vs = 0`, `am = 0`.
#> Caused by error in `across()`:
#> ! Can't compute column `mpg_mean.wted`.
#> Caused by error in `weighted.mean.default()`:
#> ! object 'cyl' not found
#> Backtrace:
#> ▆
#> 1. ├─mtcars %>% ...
#> 2. ├─global fnc(...)
#> 3. │ └─data %>% group_by(across({{ group.vars }})) %>% ...
#> 4. ├─dplyr::summarise(...)
#> 5. ├─dplyr:::summarise.grouped_df(...)
#> 6. │ └─dplyr:::summarise_cols(.data, dplyr_quosures(...), by, "summarise")
#> 7. │ ├─base::withCallingHandlers(...)
#> 8. │ └─dplyr:::map(quosures, summarise_eval_one, mask = mask)
#> 9. │ └─base::lapply(.x, .f, ...)
#> 10. │ └─dplyr (local) FUN(X[[i]], ...)
#> 11. │ ├─base::withCallingHandlers(...)
#> 12. │ └─mask$eval_all_summarise(quo)
#> 13. │ └─dplyr (local) eval()
#> 14. ├─`<rlng_lm_>`(mpg)
#> 15. │ ├─stats::weighted.mean(., w = cyl, na.rm = TRUE)
#> 16. │ └─stats:::weighted.mean.default(., w = cyl, na.rm = TRUE)
#> 17. └─base::.handleSimpleError(...)
#> 18. └─dplyr (local) h(simpleError(msg, call))
#> 19. └─rlang::abort(msg, call = call("across"), parent = cnd)
sessionInfo()
#> R version 4.2.2 (2022-10-31)
#> Platform: aarch64-apple-darwin20 (64-bit)
#> Running under: macOS Ventura 13.2.1
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRlapack.dylib
#>
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] dplyr_1.1.1
#>
#> loaded via a namespace (and not attached):
#> [1] rstudioapi_0.14 knitr_1.42 magrittr_2.0.3 tidyselect_1.2.0
#> [5] R.cache_0.16.0 R6_2.5.1 rlang_1.1.0.9000 fastmap_1.1.1
#> [9] fansi_1.0.4 styler_1.9.1 tools_4.2.2 xfun_0.37
#> [13] R.oo_1.25.0 utf8_1.2.3 cli_3.6.0 withr_2.5.0
#> [17] htmltools_0.5.4 yaml_2.3.7 digest_0.6.31 tibble_3.2.1
#> [21] lifecycle_1.0.3 purrr_1.0.1 vctrs_0.6.0.9000 R.utils_2.12.2
#> [25] fs_1.6.1 glue_1.6.2 evaluate_0.20 rmarkdown_2.20
#> [29] reprex_2.0.2 compiler_4.2.2 pillar_1.8.1 generics_0.1.3
#> [33] R.methodsS3_1.8.2 pkgconfig_2.0.3
Minimal reprex
1.0.10:
# pak::pak("tidyverse/[email protected]")
library(dplyr, warn.conflicts = FALSE)
df <- tibble(x = 1:5, w = 2:6)
fn <- function(data, cols, fns) {
summarise(data, across(.cols = {{cols}}, .fns = fns))
}
# Works from top level
summarise(df, across(x, ~weighted.mean(.x, w = w)))
#> # A tibble: 1 × 1
#> x
#> <dbl>
#> 1 3.5
# Works when wrapped
fn(df, x, ~weighted.mean(.x, w = w))
#> # A tibble: 1 × 1
#> x
#> <dbl>
#> 1 3.5
1.1.1:
library(dplyr, warn.conflicts = FALSE)
df <- tibble(x = 1:5, w = 2:6)
fn <- function(data, cols, fns) {
summarise(data, across(.cols = {{cols}}, .fns = fns))
}
# Works from top level
summarise(df, across(x, ~weighted.mean(.x, w = w)))
#> # A tibble: 1 × 1
#> x
#> <dbl>
#> 1 3.5
# Not when wrapped
fn(df, x, ~weighted.mean(.x, w = w))
#> Error in `summarise()`:
#> ℹ In argument: `across(.cols = x, .fns = fns)`.
#> Caused by error in `across()`:
#> ! Can't compute column `x`.
#> Caused by error in `weighted.mean.default()`:
#> ! object 'w' not found
Possible solution proposed by @lionel- is to allow .fns = {{ fns }}
so that users can wrap with a pattern like:
fn <- function(data, cols, fns) {
summarise(data, across(.cols = {{cols}}, .fns = {{fns}}))
}
The justification here being that if across()
is a true templating function then it needs to be able to access the original expressions for .fns
, so they need to come through with {{
Actually, that already works (assuming I'm understanding what you and @lionel- had in mind):
library(tidyverse)
fn <- function(data, cols, fns, groups=NULL) {
data %>%
group_by(across({{groups}})) %>%
summarise(across(.cols = {{cols}}, .fns = {{fns}}))
}
d = tibble(
x1=1:5, x2=11:15, w=2:6, g=rep(LETTERS[1:2], c(2,3))
)
fn(d,
cols=c(x1,x2),
fns=c(mean=mean, mean.wt=~weighted.mean(., w=w)),
groups=g)
#> # A tibble: 2 × 5
#> g x1_mean x1_mean.wt x2_mean x2_mean.wt
#> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 A 1.5 1.6 11.5 11.6
#> 2 B 4 4.13 14 14.1
fn(mtcars,
cols=c(mpg, hp),
fns=c(mean=mean, mean.wt=~weighted.mean(., w=cyl)),
groups=c(am, vs))
#> `summarise()` has grouped output by 'am'. You can override using the `.groups`
#> argument.
#> # A tibble: 4 × 6
#> # Groups: am [2]
#> am vs mpg_mean mpg_mean.wt hp_mean hp_mean.wt
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 0 0 15.0 15.1 194. 194.
#> 2 0 1 20.7 20.4 102. 105.
#> 3 1 0 19.8 19.0 181. 198.
#> 4 1 1 28.4 28.4 80.6 80.6
Created on 2023-03-31 with reprex v2.0.2
Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.2.2 (2022-10-31)
#> os macOS Ventura 13.2.1
#> system aarch64, darwin20
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz America/Los_Angeles
#> date 2023-03-31
#> pandoc 2.19.2 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> cli 3.6.1 2023-03-23 [1] CRAN (R 4.2.0)
#> colorspace 2.1-0 2023-01-23 [1] CRAN (R 4.2.0)
#> digest 0.6.31 2022-12-11 [1] CRAN (R 4.2.0)
#> dplyr * 1.1.1 2023-03-22 [1] CRAN (R 4.2.0)
#> evaluate 0.20 2023-01-17 [1] CRAN (R 4.2.0)
#> fansi 1.0.4 2023-01-22 [1] CRAN (R 4.2.0)
#> fastmap 1.1.1 2023-02-24 [1] CRAN (R 4.2.0)
#> forcats * 1.0.0 2023-01-29 [1] CRAN (R 4.2.0)
#> fs 1.6.1 2023-02-06 [1] CRAN (R 4.2.0)
#> generics 0.1.3 2022-07-05 [1] CRAN (R 4.2.0)
#> ggplot2 * 3.4.1 2023-02-10 [1] CRAN (R 4.2.0)
#> glue 1.6.2 2022-02-24 [1] CRAN (R 4.2.0)
#> gtable 0.3.3 2023-03-21 [1] CRAN (R 4.2.0)
#> hms 1.1.3 2023-03-21 [1] CRAN (R 4.2.0)
#> htmltools 0.5.5 2023-03-23 [1] CRAN (R 4.2.0)
#> knitr 1.42 2023-01-25 [1] CRAN (R 4.2.0)
#> lifecycle 1.0.3 2022-10-07 [1] CRAN (R 4.2.0)
#> lubridate * 1.9.2 2023-02-10 [1] CRAN (R 4.2.0)
#> magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.2.0)
#> munsell 0.5.0 2018-06-12 [1] CRAN (R 4.2.0)
#> pillar 1.9.0 2023-03-22 [1] CRAN (R 4.2.0)
#> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.2.0)
#> purrr * 1.0.1 2023-01-10 [1] CRAN (R 4.2.0)
#> R.cache 0.16.0 2022-07-21 [1] CRAN (R 4.2.0)
#> R.methodsS3 1.8.2 2022-06-13 [1] CRAN (R 4.2.0)
#> R.oo 1.25.0 2022-06-12 [1] CRAN (R 4.2.0)
#> R.utils 2.12.2 2022-11-11 [1] CRAN (R 4.2.0)
#> R6 2.5.1 2021-08-19 [1] CRAN (R 4.2.0)
#> readr * 2.1.4 2023-02-10 [1] CRAN (R 4.2.0)
#> reprex 2.0.2 2022-08-17 [1] CRAN (R 4.2.0)
#> rlang 1.1.0.9000 2023-03-21 [1] Github (r-lib/rlang@ea2fe5f)
#> rmarkdown 2.21 2023-03-26 [1] CRAN (R 4.2.2)
#> rstudioapi 0.14 2022-08-22 [1] CRAN (R 4.2.0)
#> scales 1.2.1 2022-08-20 [1] CRAN (R 4.2.0)
#> sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.2.0)
#> stringi 1.7.12 2023-01-11 [1] CRAN (R 4.2.0)
#> stringr * 1.5.0 2022-12-02 [1] CRAN (R 4.2.0)
#> styler 1.9.1 2023-03-04 [1] CRAN (R 4.2.0)
#> tibble * 3.2.1 2023-03-20 [1] CRAN (R 4.2.0)
#> tidyr * 1.3.0 2023-01-24 [1] CRAN (R 4.2.0)
#> tidyselect 1.2.0 2022-10-10 [1] CRAN (R 4.2.0)
#> tidyverse * 2.0.0 2023-02-22 [1] CRAN (R 4.2.0)
#> timechange 0.2.0 2023-01-11 [1] CRAN (R 4.2.2)
#> tzdb 0.3.0 2022-03-28 [1] CRAN (R 4.2.0)
#> utf8 1.2.3 2023-01-31 [1] CRAN (R 4.2.0)
#> vctrs 0.6.1 2023-03-22 [1] CRAN (R 4.2.0)
#> withr 2.5.0 2022-03-03 [1] CRAN (R 4.2.0)
#> xfun 0.38 2023-03-24 [1] CRAN (R 4.2.0)
#> yaml 2.3.7 2023-01-23 [1] CRAN (R 4.2.0)
#>
#> [1] /Users/***/Library/R/arm64/4.2/library
#> [2] /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library
#>
#> ──────────────────────────────────────────────────────────────────────────────
Oh, but it doesn't work if you pass a separate object as the fns
argument:
library(tidyverse)
fn <- function(data, cols, fns, groups=NULL) {
data %>%
group_by(across({{groups}})) %>%
summarise(across(.cols = {{cols}}, .fns = {{fns}}))
}
fn(mtcars,
cols=c(mpg, hp),
fns=c(mean=mean, mean.wt=~weighted.mean(., w=cyl)),
groups=c(am, vs))
#> `summarise()` has grouped output by 'am'. You can override using the `.groups`
#> argument.
#> # A tibble: 4 × 6
#> # Groups: am [2]
#> am vs mpg_mean mpg_mean.wt hp_mean hp_mean.wt
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 0 0 15.0 15.1 194. 194.
#> 2 0 1 20.7 20.4 102. 105.
#> 3 1 0 19.8 19.0 181. 198.
#> 4 1 1 28.4 28.4 80.6 80.6
FUNS = c(mean=mean, mean.wt=~weighted.mean(., w=cyl))
fn(mtcars,
cols=c(mpg, hp),
fns=FUNS,
groups=c(am, vs))
#> Error in `summarise()`:
#> ℹ In argument: `across(.cols = c(mpg, hp), .fns = FUNS)`.
#> ℹ In group 1: `am = 0`, `vs = 0`.
#> Caused by error in `across()`:
#> ! Can't compute column `mpg_mean.wt`.
#> Caused by error in `weighted.mean.default()`:
#> ! object 'cyl' not found
#> Backtrace:
#> ▆
#> 1. ├─global fn(mtcars, cols = c(mpg, hp), fns = FUNS, groups = c(am, vs))
#> 2. │ └─data %>% group_by(across({{ groups }})) %>% ...
#> 3. ├─dplyr::summarise(...)
#> 4. ├─dplyr:::summarise.grouped_df(...)
#> 5. │ └─dplyr:::summarise_cols(.data, dplyr_quosures(...), by, "summarise")
#> 6. │ ├─base::withCallingHandlers(...)
#> 7. │ └─dplyr:::map(quosures, summarise_eval_one, mask = mask)
#> 8. │ └─base::lapply(.x, .f, ...)
#> 9. │ └─dplyr (local) FUN(X[[i]], ...)
#> 10. │ ├─base::withCallingHandlers(...)
#> 11. │ └─mask$eval_all_summarise(quo)
#> 12. │ └─dplyr (local) eval()
#> 13. ├─global `<rlng_lm_>`(mpg)
#> 14. │ ├─stats::weighted.mean(., w = cyl)
#> 15. │ └─stats:::weighted.mean.default(., w = cyl)
#> 16. └─base::.handleSimpleError(...)
#> 17. └─dplyr (local) h(simpleError(msg, call))
#> 18. └─rlang::abort(msg, call = call("across"), parent = cnd)
Created on 2023-04-01 with reprex v2.0.2
Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.2.2 (2022-10-31)
#> os macOS Ventura 13.2.1
#> system aarch64, darwin20
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz America/Los_Angeles
#> date 2023-04-01
#> pandoc 2.19.2 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> cli 3.6.1 2023-03-23 [1] CRAN (R 4.2.0)
#> colorspace 2.1-0 2023-01-23 [1] CRAN (R 4.2.0)
#> digest 0.6.31 2022-12-11 [1] CRAN (R 4.2.0)
#> dplyr * 1.1.1 2023-03-22 [1] CRAN (R 4.2.0)
#> evaluate 0.20 2023-01-17 [1] CRAN (R 4.2.0)
#> fansi 1.0.4 2023-01-22 [1] CRAN (R 4.2.0)
#> fastmap 1.1.1 2023-02-24 [1] CRAN (R 4.2.0)
#> forcats * 1.0.0 2023-01-29 [1] CRAN (R 4.2.0)
#> fs 1.6.1 2023-02-06 [1] CRAN (R 4.2.0)
#> generics 0.1.3 2022-07-05 [1] CRAN (R 4.2.0)
#> ggplot2 * 3.4.1 2023-02-10 [1] CRAN (R 4.2.0)
#> glue 1.6.2 2022-02-24 [1] CRAN (R 4.2.0)
#> gtable 0.3.3 2023-03-21 [1] CRAN (R 4.2.0)
#> hms 1.1.3 2023-03-21 [1] CRAN (R 4.2.0)
#> htmltools 0.5.5 2023-03-23 [1] CRAN (R 4.2.0)
#> knitr 1.42 2023-01-25 [1] CRAN (R 4.2.0)
#> lifecycle 1.0.3 2022-10-07 [1] CRAN (R 4.2.0)
#> lubridate * 1.9.2 2023-02-10 [1] CRAN (R 4.2.0)
#> magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.2.0)
#> munsell 0.5.0 2018-06-12 [1] CRAN (R 4.2.0)
#> pillar 1.9.0 2023-03-22 [1] CRAN (R 4.2.0)
#> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.2.0)
#> purrr * 1.0.1 2023-01-10 [1] CRAN (R 4.2.0)
#> R.cache 0.16.0 2022-07-21 [1] CRAN (R 4.2.0)
#> R.methodsS3 1.8.2 2022-06-13 [1] CRAN (R 4.2.0)
#> R.oo 1.25.0 2022-06-12 [1] CRAN (R 4.2.0)
#> R.utils 2.12.2 2022-11-11 [1] CRAN (R 4.2.0)
#> R6 2.5.1 2021-08-19 [1] CRAN (R 4.2.0)
#> readr * 2.1.4 2023-02-10 [1] CRAN (R 4.2.0)
#> reprex 2.0.2 2022-08-17 [1] CRAN (R 4.2.0)
#> rlang 1.1.0.9000 2023-03-21 [1] Github (r-lib/rlang@ea2fe5f)
#> rmarkdown 2.21 2023-03-26 [1] CRAN (R 4.2.2)
#> rstudioapi 0.14 2022-08-22 [1] CRAN (R 4.2.0)
#> scales 1.2.1 2022-08-20 [1] CRAN (R 4.2.0)
#> sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.2.0)
#> stringi 1.7.12 2023-01-11 [1] CRAN (R 4.2.0)
#> stringr * 1.5.0 2022-12-02 [1] CRAN (R 4.2.0)
#> styler 1.9.1 2023-03-04 [1] CRAN (R 4.2.0)
#> tibble * 3.2.1 2023-03-20 [1] CRAN (R 4.2.0)
#> tidyr * 1.3.0 2023-01-24 [1] CRAN (R 4.2.0)
#> tidyselect 1.2.0 2022-10-10 [1] CRAN (R 4.2.0)
#> tidyverse * 2.0.0 2023-02-22 [1] CRAN (R 4.2.0)
#> timechange 0.2.0 2023-01-11 [1] CRAN (R 4.2.2)
#> tzdb 0.3.0 2022-03-28 [1] CRAN (R 4.2.0)
#> utf8 1.2.3 2023-01-31 [1] CRAN (R 4.2.0)
#> vctrs 0.6.1 2023-03-22 [1] CRAN (R 4.2.0)
#> withr 2.5.0 2022-03-03 [1] CRAN (R 4.2.0)
#> xfun 0.38 2023-03-24 [1] CRAN (R 4.2.0)
#> yaml 2.3.7 2023-01-23 [1] CRAN (R 4.2.0)
#>
#> [1] /Users/jschwartz/Library/R/arm64/4.2/library
#> [2] /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library
#>
#> ──────────────────────────────────────────────────────────────────────────────
That probably can't and won't ever work because we can't "see" the expression that built the original object, we only see FUNS
As a result of my incomplete understanding of how NSE might interact with different ways of passing arguments, I failed to include a separate FUNS
object as an example in my initial post.
I just want to point out that in dplyr 1.0.10
you can pass a separate FUNS
object into a summary function, without using embrasure, and the summary function works, even when you pass additional columns inside one or more of the functions within FUNS
, such as the w
argument in weighted.mean
. But this approach fails in dplyr 1.1.1
. Because I do this often, I ran into this problem almost immediately after I installed 1.1.1. Below are reproducible examples with 1.0.10 and 1.1.1.
You can pass the .fns argument explicitly if you use embrasure, as in my post above, but how can I make the FUNS
example below work in 1.1.1 as it does in 1.0.10 (preferably in a way that also works with an explicit .fns argument)?
dplyr 1.0.10
: Passing an (unembraced) .fns
(directly or as an object) works
library(tidyverse)
fn <- function(data, cols, fns, groups=NULL) {
data %>%
group_by(across({{groups}})) %>%
summarise(across(.cols = {{cols}}, .fns = fns))
}
fn(mtcars,
cols=c(mpg, hp),
fns=c(mean=mean, mean.wt=~weighted.mean(., w=cyl)),
groups=c(am, vs))
#> `summarise()` has grouped output by 'am'. You can override using the `.groups`
#> argument.
#> # A tibble: 4 × 6
#> # Groups: am [2]
#> am vs mpg_mean mpg_mean.wt hp_mean hp_mean.wt
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 0 0 15.0 15.1 194. 194.
#> 2 0 1 20.7 20.4 102. 105.
#> 3 1 0 19.8 19.0 181. 198.
#> 4 1 1 28.4 28.4 80.6 80.6
FUNS = c(mean=mean, mean.wt=~weighted.mean(., w=cyl))
fn(mtcars,
cols=c(mpg, hp),
fns=FUNS,
groups=c(am, vs))
#> `summarise()` has grouped output by 'am'. You can override using the `.groups`
#> argument.
#> # A tibble: 4 × 6
#> # Groups: am [2]
#> am vs mpg_mean mpg_mean.wt hp_mean hp_mean.wt
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 0 0 15.0 15.1 194. 194.
#> 2 0 1 20.7 20.4 102. 105.
#> 3 1 0 19.8 19.0 181. 198.
#> 4 1 1 28.4 28.4 80.6 80.6
Created on 2023-04-01 with reprex v2.0.2
Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.2.2 (2022-10-31)
#> os macOS Ventura 13.2.1
#> system aarch64, darwin20
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz America/Los_Angeles
#> date 2023-04-01
#> pandoc 2.19.2 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> cli 3.6.1 2023-03-23 [1] CRAN (R 4.2.0)
#> colorspace 2.1-0 2023-01-23 [1] CRAN (R 4.2.0)
#> DBI 1.1.3 2022-06-18 [1] CRAN (R 4.2.0)
#> digest 0.6.31 2022-12-11 [1] CRAN (R 4.2.0)
#> dplyr * 1.0.10 2022-09-01 [1] CRAN (R 4.2.2)
#> evaluate 0.20 2023-01-17 [1] CRAN (R 4.2.0)
#> fansi 1.0.4 2023-01-22 [1] CRAN (R 4.2.0)
#> fastmap 1.1.1 2023-02-24 [1] CRAN (R 4.2.0)
#> forcats * 1.0.0 2023-01-29 [1] CRAN (R 4.2.0)
#> fs 1.6.1 2023-02-06 [1] CRAN (R 4.2.0)
#> generics 0.1.3 2022-07-05 [1] CRAN (R 4.2.0)
#> ggplot2 * 3.4.1 2023-02-10 [1] CRAN (R 4.2.0)
#> glue 1.6.2 2022-02-24 [1] CRAN (R 4.2.0)
#> gtable 0.3.3 2023-03-21 [1] CRAN (R 4.2.0)
#> hms 1.1.3 2023-03-21 [1] CRAN (R 4.2.0)
#> htmltools 0.5.5 2023-03-23 [1] CRAN (R 4.2.0)
#> knitr 1.42 2023-01-25 [1] CRAN (R 4.2.0)
#> lifecycle 1.0.3 2022-10-07 [1] CRAN (R 4.2.0)
#> lubridate * 1.9.2 2023-02-10 [1] CRAN (R 4.2.0)
#> magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.2.0)
#> munsell 0.5.0 2018-06-12 [1] CRAN (R 4.2.0)
#> pillar 1.9.0 2023-03-22 [1] CRAN (R 4.2.0)
#> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.2.0)
#> purrr * 1.0.1 2023-01-10 [1] CRAN (R 4.2.0)
#> R.cache 0.16.0 2022-07-21 [1] CRAN (R 4.2.0)
#> R.methodsS3 1.8.2 2022-06-13 [1] CRAN (R 4.2.0)
#> R.oo 1.25.0 2022-06-12 [1] CRAN (R 4.2.0)
#> R.utils 2.12.2 2022-11-11 [1] CRAN (R 4.2.0)
#> R6 2.5.1 2021-08-19 [1] CRAN (R 4.2.0)
#> readr * 2.1.4 2023-02-10 [1] CRAN (R 4.2.0)
#> reprex 2.0.2 2022-08-17 [1] CRAN (R 4.2.0)
#> rlang 1.1.0.9000 2023-03-21 [1] Github (r-lib/rlang@ea2fe5f)
#> rmarkdown 2.21 2023-03-26 [1] CRAN (R 4.2.2)
#> rstudioapi 0.14 2022-08-22 [1] CRAN (R 4.2.0)
#> scales 1.2.1 2022-08-20 [1] CRAN (R 4.2.0)
#> sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.2.0)
#> stringi 1.7.12 2023-01-11 [1] CRAN (R 4.2.0)
#> stringr * 1.5.0 2022-12-02 [1] CRAN (R 4.2.0)
#> styler 1.9.1 2023-03-04 [1] CRAN (R 4.2.0)
#> tibble * 3.2.1 2023-03-20 [1] CRAN (R 4.2.0)
#> tidyr * 1.3.0 2023-01-24 [1] CRAN (R 4.2.0)
#> tidyselect 1.2.0 2022-10-10 [1] CRAN (R 4.2.0)
#> tidyverse * 2.0.0 2023-02-22 [1] CRAN (R 4.2.0)
#> timechange 0.2.0 2023-01-11 [1] CRAN (R 4.2.2)
#> tzdb 0.3.0 2022-03-28 [1] CRAN (R 4.2.0)
#> utf8 1.2.3 2023-01-31 [1] CRAN (R 4.2.0)
#> vctrs 0.6.1 2023-03-22 [1] CRAN (R 4.2.0)
#> withr 2.5.0 2022-03-03 [1] CRAN (R 4.2.0)
#> xfun 0.38 2023-03-24 [1] CRAN (R 4.2.0)
#> yaml 2.3.7 2023-01-23 [1] CRAN (R 4.2.0)
#>
#> [1] /Users/jschwartz/Library/R/arm64/4.2/library
#> [2] /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library
#>
#> ──────────────────────────────────────────────────────────────────────────────
dplyr 1.1.1
: Passing an (unembraced) .fns
(directly or as an object) fails
library(tidyverse)
fn <- function(data, cols, fns, groups=NULL) {
data %>%
group_by(across({{groups}})) %>%
summarise(across(.cols = {{cols}}, .fns = fns))
}
fn(mtcars,
cols=c(mpg, hp),
fns=c(mean=mean, mean.wt=~weighted.mean(., w=cyl)),
groups=c(am, vs))
#> Error in `summarise()`:
#> ℹ In argument: `across(.cols = c(mpg, hp), .fns = fns)`.
#> ℹ In group 1: `am = 0`, `vs = 0`.
#> Caused by error in `across()`:
#> ! Can't compute column `mpg_mean.wt`.
#> Caused by error in `weighted.mean.default()`:
#> ! object 'cyl' not found
#> Backtrace:
#> ▆
#> 1. ├─global fn(...)
#> 2. │ └─data %>% group_by(across({{ groups }})) %>% ...
#> 3. ├─dplyr::summarise(...)
#> 4. ├─dplyr:::summarise.grouped_df(...)
#> 5. │ └─dplyr:::summarise_cols(.data, dplyr_quosures(...), by, "summarise")
#> 6. │ ├─base::withCallingHandlers(...)
#> 7. │ └─dplyr:::map(quosures, summarise_eval_one, mask = mask)
#> 8. │ └─base::lapply(.x, .f, ...)
#> 9. │ └─dplyr (local) FUN(X[[i]], ...)
#> 10. │ ├─base::withCallingHandlers(...)
#> 11. │ └─mask$eval_all_summarise(quo)
#> 12. │ └─dplyr (local) eval()
#> 13. ├─global `<rlng_lm_>`(mpg)
#> 14. │ ├─stats::weighted.mean(., w = cyl)
#> 15. │ └─stats:::weighted.mean.default(., w = cyl)
#> 16. └─base::.handleSimpleError(...)
#> 17. └─dplyr (local) h(simpleError(msg, call))
#> 18. └─rlang::abort(msg, call = call("across"), parent = cnd)
FUNS = c(mean=mean, mean.wt=~weighted.mean(., w=cyl))
fn(mtcars,
cols=c(mpg, hp),
fns=FUNS,
groups=c(am, vs))
#> Error in `summarise()`:
#> ℹ In argument: `across(.cols = c(mpg, hp), .fns = fns)`.
#> ℹ In group 1: `am = 0`, `vs = 0`.
#> Caused by error in `across()`:
#> ! Can't compute column `mpg_mean.wt`.
#> Caused by error in `weighted.mean.default()`:
#> ! object 'cyl' not found
#> Backtrace:
#> ▆
#> 1. ├─global fn(mtcars, cols = c(mpg, hp), fns = FUNS, groups = c(am, vs))
#> 2. │ └─data %>% group_by(across({{ groups }})) %>% ...
#> 3. ├─dplyr::summarise(...)
#> 4. ├─dplyr:::summarise.grouped_df(...)
#> 5. │ └─dplyr:::summarise_cols(.data, dplyr_quosures(...), by, "summarise")
#> 6. │ ├─base::withCallingHandlers(...)
#> 7. │ └─dplyr:::map(quosures, summarise_eval_one, mask = mask)
#> 8. │ └─base::lapply(.x, .f, ...)
#> 9. │ └─dplyr (local) FUN(X[[i]], ...)
#> 10. │ ├─base::withCallingHandlers(...)
#> 11. │ └─mask$eval_all_summarise(quo)
#> 12. │ └─dplyr (local) eval()
#> 13. ├─global `<rlng_lm_>`(mpg)
#> 14. │ ├─stats::weighted.mean(., w = cyl)
#> 15. │ └─stats:::weighted.mean.default(., w = cyl)
#> 16. └─base::.handleSimpleError(...)
#> 17. └─dplyr (local) h(simpleError(msg, call))
#> 18. └─rlang::abort(msg, call = call("across"), parent = cnd)
Created on 2023-04-01 with reprex v2.0.2
Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.2.2 (2022-10-31)
#> os macOS Ventura 13.2.1
#> system aarch64, darwin20
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz America/Los_Angeles
#> date 2023-04-01
#> pandoc 2.19.2 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> cli 3.6.1 2023-03-23 [1] CRAN (R 4.2.0)
#> colorspace 2.1-0 2023-01-23 [1] CRAN (R 4.2.0)
#> digest 0.6.31 2022-12-11 [1] CRAN (R 4.2.0)
#> dplyr * 1.1.1 2023-03-22 [1] CRAN (R 4.2.2)
#> evaluate 0.20 2023-01-17 [1] CRAN (R 4.2.0)
#> fansi 1.0.4 2023-01-22 [1] CRAN (R 4.2.0)
#> fastmap 1.1.1 2023-02-24 [1] CRAN (R 4.2.0)
#> forcats * 1.0.0 2023-01-29 [1] CRAN (R 4.2.0)
#> fs 1.6.1 2023-02-06 [1] CRAN (R 4.2.0)
#> generics 0.1.3 2022-07-05 [1] CRAN (R 4.2.0)
#> ggplot2 * 3.4.1 2023-02-10 [1] CRAN (R 4.2.0)
#> glue 1.6.2 2022-02-24 [1] CRAN (R 4.2.0)
#> gtable 0.3.3 2023-03-21 [1] CRAN (R 4.2.0)
#> hms 1.1.3 2023-03-21 [1] CRAN (R 4.2.0)
#> htmltools 0.5.5 2023-03-23 [1] CRAN (R 4.2.0)
#> knitr 1.42 2023-01-25 [1] CRAN (R 4.2.0)
#> lifecycle 1.0.3 2022-10-07 [1] CRAN (R 4.2.0)
#> lubridate * 1.9.2 2023-02-10 [1] CRAN (R 4.2.0)
#> magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.2.0)
#> munsell 0.5.0 2018-06-12 [1] CRAN (R 4.2.0)
#> pillar 1.9.0 2023-03-22 [1] CRAN (R 4.2.0)
#> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.2.0)
#> purrr * 1.0.1 2023-01-10 [1] CRAN (R 4.2.0)
#> R.cache 0.16.0 2022-07-21 [1] CRAN (R 4.2.0)
#> R.methodsS3 1.8.2 2022-06-13 [1] CRAN (R 4.2.0)
#> R.oo 1.25.0 2022-06-12 [1] CRAN (R 4.2.0)
#> R.utils 2.12.2 2022-11-11 [1] CRAN (R 4.2.0)
#> R6 2.5.1 2021-08-19 [1] CRAN (R 4.2.0)
#> readr * 2.1.4 2023-02-10 [1] CRAN (R 4.2.0)
#> reprex 2.0.2 2022-08-17 [1] CRAN (R 4.2.0)
#> rlang 1.1.0.9000 2023-03-21 [1] Github (r-lib/rlang@ea2fe5f)
#> rmarkdown 2.21 2023-03-26 [1] CRAN (R 4.2.2)
#> rstudioapi 0.14 2022-08-22 [1] CRAN (R 4.2.0)
#> scales 1.2.1 2022-08-20 [1] CRAN (R 4.2.0)
#> sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.2.0)
#> stringi 1.7.12 2023-01-11 [1] CRAN (R 4.2.0)
#> stringr * 1.5.0 2022-12-02 [1] CRAN (R 4.2.0)
#> styler 1.9.1 2023-03-04 [1] CRAN (R 4.2.0)
#> tibble * 3.2.1 2023-03-20 [1] CRAN (R 4.2.0)
#> tidyr * 1.3.0 2023-01-24 [1] CRAN (R 4.2.0)
#> tidyselect 1.2.0 2022-10-10 [1] CRAN (R 4.2.0)
#> tidyverse * 2.0.0 2023-02-22 [1] CRAN (R 4.2.0)
#> timechange 0.2.0 2023-01-11 [1] CRAN (R 4.2.2)
#> tzdb 0.3.0 2022-03-28 [1] CRAN (R 4.2.0)
#> utf8 1.2.3 2023-01-31 [1] CRAN (R 4.2.0)
#> vctrs 0.6.1 2023-03-22 [1] CRAN (R 4.2.0)
#> withr 2.5.0 2022-03-03 [1] CRAN (R 4.2.0)
#> xfun 0.38 2023-03-24 [1] CRAN (R 4.2.0)
#> yaml 2.3.7 2023-01-23 [1] CRAN (R 4.2.0)
#>
#> [1] /Users/jschwartz/Library/R/arm64/4.2/library
#> [2] /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library
#>
#> ──────────────────────────────────────────────────────────────────────────────
I believe that the new behavior was introduced in https://github.com/tidyverse/dplyr/pull/6550 IMO, the new behavior is better, it removes ambiguities. For example, in the above example,
fn <- function(data, cols, fns, groups=NULL) {
data %>%
group_by(across({{groups}})) %>%
summarise(across(.cols = {{cols}}, .fns = fns))
}
fn(mtcars,
cols=c(mpg, hp),
fns=c(mean=mean, mean.wt=~weighted.mean(., w=cyl)),
groups=c(am, vs))
It is unclear if cyl
should be from the data frame or a global variable.
I would expect cyl
to be picked up from the data frame in that example, consistently with dplyr semantics. This can be achieved by interpolating .fns
with .fns = {{ .fns }}
. We'll test and document this as an official pattern.
@lionel- the code below fails in dplyr 1.1.1
even though it uses embracing operator, so I think I'm not understanding your previous comment. Is there a different pattern I should be using to pass FUNS
into a summarizing function in a way that will work with weighted.mean
(or other functions that similarly require ancillary columns to be passed into the .fns
argument)?
library(tidyverse)
fn <- function(data, cols, fns, groups=NULL) {
data %>%
group_by(across({{groups}})) %>%
summarise(across(.cols = {{cols}}, .fns = {{fns}}))
}
FUNS = c(mean=mean, mean.wt=~weighted.mean(., w=cyl))
fn(mtcars,
cols=c(mpg, hp),
fns=FUNS,
groups=c(am, vs))
#> Error in `summarise()`:
#> ℹ In argument: `across(.cols = c(mpg, hp), .fns = FUNS)`.
#> ℹ In group 1: `am = 0`, `vs = 0`.
#> Caused by error in `across()`:
#> ! Can't compute column `mpg_mean.wt`.
#> Caused by error in `weighted.mean.default()`:
#> ! object 'cyl' not found
#> Backtrace:
#> ▆
#> 1. ├─global fn(mtcars, cols = c(mpg, hp), fns = FUNS, groups = c(am, vs))
#> 2. │ └─data %>% group_by(across({{ groups }})) %>% ...
#> 3. ├─dplyr::summarise(...)
#> 4. ├─dplyr:::summarise.grouped_df(...)
#> 5. │ └─dplyr:::summarise_cols(.data, dplyr_quosures(...), by, "summarise")
#> 6. │ ├─base::withCallingHandlers(...)
#> 7. │ └─dplyr:::map(quosures, summarise_eval_one, mask = mask)
#> 8. │ └─base::lapply(.x, .f, ...)
#> 9. │ └─dplyr (local) FUN(X[[i]], ...)
#> 10. │ ├─base::withCallingHandlers(...)
#> 11. │ └─mask$eval_all_summarise(quo)
#> 12. │ └─dplyr (local) eval()
#> 13. ├─global `<rlng_lm_>`(mpg)
#> 14. │ ├─stats::weighted.mean(., w = cyl)
#> 15. │ └─stats:::weighted.mean.default(., w = cyl)
#> 16. └─base::.handleSimpleError(...)
#> 17. └─dplyr (local) h(simpleError(msg, call))
#> 18. └─rlang::abort(msg, call = call("across"), parent = cnd)
Created on 2023-04-06 with reprex v2.0.2
Session info
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.2.3 (2023-03-15)
#> os macOS Ventura 13.2.1
#> system aarch64, darwin20
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz America/Los_Angeles
#> date 2023-04-06
#> pandoc 2.19.2 @ /Applications/RStudio.app/Contents/Resources/app/quarto/bin/tools/ (via rmarkdown)
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> cli 3.6.1 2023-03-23 [1] CRAN (R 4.2.0)
#> colorspace 2.1-0 2023-01-23 [1] CRAN (R 4.2.0)
#> digest 0.6.31 2022-12-11 [1] CRAN (R 4.2.0)
#> dplyr * 1.1.1 2023-03-22 [1] CRAN (R 4.2.2)
#> evaluate 0.20 2023-01-17 [1] CRAN (R 4.2.0)
#> fansi 1.0.4 2023-01-22 [1] CRAN (R 4.2.0)
#> fastmap 1.1.1 2023-02-24 [1] CRAN (R 4.2.0)
#> forcats * 1.0.0 2023-01-29 [1] CRAN (R 4.2.0)
#> fs 1.6.1 2023-02-06 [1] CRAN (R 4.2.0)
#> generics 0.1.3 2022-07-05 [1] CRAN (R 4.2.0)
#> ggplot2 * 3.4.2 2023-04-03 [1] CRAN (R 4.2.0)
#> glue 1.6.2 2022-02-24 [1] CRAN (R 4.2.0)
#> gtable 0.3.3 2023-03-21 [1] CRAN (R 4.2.0)
#> hms 1.1.3 2023-03-21 [1] CRAN (R 4.2.0)
#> htmltools 0.5.5 2023-03-23 [1] CRAN (R 4.2.0)
#> knitr 1.42 2023-01-25 [1] CRAN (R 4.2.0)
#> lifecycle 1.0.3 2022-10-07 [1] CRAN (R 4.2.0)
#> lubridate * 1.9.2 2023-02-10 [1] CRAN (R 4.2.0)
#> magrittr 2.0.3 2022-03-30 [1] CRAN (R 4.2.0)
#> munsell 0.5.0 2018-06-12 [1] CRAN (R 4.2.0)
#> pillar 1.9.0 2023-03-22 [1] CRAN (R 4.2.0)
#> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.2.0)
#> purrr * 1.0.1 2023-01-10 [1] CRAN (R 4.2.0)
#> R.cache 0.16.0 2022-07-21 [1] CRAN (R 4.2.0)
#> R.methodsS3 1.8.2 2022-06-13 [1] CRAN (R 4.2.0)
#> R.oo 1.25.0 2022-06-12 [1] CRAN (R 4.2.0)
#> R.utils 2.12.2 2022-11-11 [1] CRAN (R 4.2.0)
#> R6 2.5.1 2021-08-19 [1] CRAN (R 4.2.0)
#> readr * 2.1.4 2023-02-10 [1] CRAN (R 4.2.0)
#> reprex 2.0.2 2022-08-17 [1] CRAN (R 4.2.0)
#> rlang 1.1.0.9000 2023-03-21 [1] Github (r-lib/rlang@ea2fe5f)
#> rmarkdown 2.21 2023-03-26 [1] CRAN (R 4.2.2)
#> rstudioapi 0.14 2022-08-22 [1] CRAN (R 4.2.0)
#> scales 1.2.1 2022-08-20 [1] CRAN (R 4.2.0)
#> sessioninfo 1.2.2 2021-12-06 [1] CRAN (R 4.2.0)
#> stringi 1.7.12 2023-01-11 [1] CRAN (R 4.2.0)
#> stringr * 1.5.0 2022-12-02 [1] CRAN (R 4.2.0)
#> styler 1.9.1 2023-03-04 [1] CRAN (R 4.2.0)
#> tibble * 3.2.1 2023-03-20 [1] CRAN (R 4.2.0)
#> tidyr * 1.3.0 2023-01-24 [1] CRAN (R 4.2.0)
#> tidyselect 1.2.0 2022-10-10 [1] CRAN (R 4.2.0)
#> tidyverse * 2.0.0 2023-02-22 [1] CRAN (R 4.2.0)
#> timechange 0.2.0 2023-01-11 [1] CRAN (R 4.2.2)
#> tzdb 0.3.0 2022-03-28 [1] CRAN (R 4.2.0)
#> utf8 1.2.3 2023-01-31 [1] CRAN (R 4.2.0)
#> vctrs 0.6.1 2023-03-22 [1] CRAN (R 4.2.0)
#> withr 2.5.0 2022-03-03 [1] CRAN (R 4.2.0)
#> xfun 0.38 2023-03-24 [1] CRAN (R 4.2.0)
#> yaml 2.3.7 2023-01-23 [1] CRAN (R 4.2.0)
#>
#> [1] /Users/jschwartz/Library/R/arm64/4.2/library
#> [2] /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/library
#>
#> ──────────────────────────────────────────────────────────────────────────────
@eipi10 It is still possible, but you need to defuse and inject the expression.
FUNS = quo(c(mean=mean, mean.wt=~weighted.mean(., w=cyl)))
fn(mtcars,
cols=c(mpg, hp),
fns=!!FUNS,
groups=c(am, vs))
Thanks @randy3k!
I found this after experiencing the identical issue- needing to use weighted.mean
with a data-variable for the weights in an across
, with weighted.mean
being one of many possible user-supplied functions. These functions are typically defined in a list by a user (or programatically), which is then passed to a function essentially the same as fn
above, essentially identically to @randy3k 's comment above.
While the solution works, it is causing headaches for users, who have to remember to wrap their list of functions in rlang::quo
sometimes and use !!
in the call. In addition, if a list of functions is generated programatically, getting that quo
wrapper is not straightforward.
I see @randy3k 's point about ambiguities, but I wonder if there's a way to explicitly remove them while avoiding the need to wrap the whole set of functions in quo
. A solution that allowed an explict data reference would remove the ambiguity, e.g.
FUNS <- list(mean = mean, mean.wt = ~weighted.mean(., w = .data$cyl)
. Is that possible?
I've tried to get that to work in a few different ways by using eval_tidy
to provide the .data
pronoun inside the summary(across))
with no success and maybe it just doesn't work- I get confused quickly trying to understand what is actually happening with the stack and what can be referenced by the time we're inside the summarize(across())
.
I used rlang::as_function()
. It seemed to work. But I am not too sure of the implications.
Just checking back here to see if there is now (or will eventually be) a better way to pass function arguments within across
. By "better," I mean better than having to remember to defuse the function(s) by wrapping in quo
and then later inject with !!
.