@@ -564,8 +564,9 @@ get_before_after_from_window <- function(window_size, align, time_type) {
564
564
# ' functions).
565
565
# '
566
566
# ' @importFrom dplyr bind_rows mutate %>% arrange tibble select all_of
567
- # ' @importFrom rlang enquo expr_label caller_arg
567
+ # ' @importFrom rlang enquo expr_label caller_arg quo_get_env
568
568
# ' @importFrom tidyselect eval_select
569
+ # ' @importFrom glue glue
569
570
# ' @importFrom purrr map map_lgl
570
571
# ' @importFrom data.table frollmean frollsum frollapply
571
572
# ' @importFrom lubridate as.period
@@ -593,6 +594,7 @@ get_before_after_from_window <- function(window_size, align, time_type) {
593
594
epi_slide_opt <- function (
594
595
.x , .col_names , .f , ... ,
595
596
.window_size = NULL , .align = c(" right" , " center" , " left" ),
597
+ .prefix = NULL , .suffix = NULL , .new_col_names = NULL ,
596
598
.ref_time_values = NULL , .all_rows = FALSE ) {
597
599
assert_class(.x , " epi_df" )
598
600
@@ -644,21 +646,37 @@ epi_slide_opt <- function(
644
646
)
645
647
}
646
648
649
+ # The position of a given column can be differ between input `.x` and
650
+ # `.data_group` since the grouping step by default drops grouping columns.
651
+ # To avoid rerunning `eval_select` for every `.data_group`, convert
652
+ # positions of user-provided `col_names` into string column names. We avoid
653
+ # using `names(pos)` directly for robustness and in case we later want to
654
+ # allow users to rename fields via tidyselection.
655
+ col_names_quo <- enquo(.col_names )
656
+ pos <- eval_select(col_names_quo , data = .x , allow_rename = FALSE )
657
+ col_names_chr <- names(.x )[pos ]
658
+
647
659
# Check that slide function `.f` is one of those short-listed from
648
660
# `data.table` and `slider` (or a function that has the exact same
649
661
# definition, e.g. if the function has been reexported or defined
650
662
# locally).
651
- if (any(map_lgl(
652
- list (frollmean , frollsum , frollapply ),
653
- ~ identical(.f , .x )
654
- ))) {
655
- f_from_package <- " data.table"
656
- } else if (any(map_lgl(
657
- list (slide_sum , slide_prod , slide_mean , slide_min , slide_max , slide_all , slide_any ),
658
- ~ identical(.f , .x )
659
- ))) {
660
- f_from_package <- " slider"
661
- } else {
663
+ f_possibilities <-
664
+ tibble :: tribble(
665
+ ~ f , ~ package , ~ abbr ,
666
+ frollmean , " data.table" , " av" ,
667
+ frollsum , " data.table" , " sum" ,
668
+ frollapply , " data.table" , " slide" ,
669
+ slide_sum , " slider" , " sum" ,
670
+ slide_prod , " slider" , " prod" ,
671
+ slide_mean , " slider" , " av" ,
672
+ slide_min , " slider" , " min" ,
673
+ slide_max , " slider" , " max" ,
674
+ slide_all , " slider" , " all" ,
675
+ slide_any , " slider" , " any" ,
676
+ )
677
+ f_info <- f_possibilities %> %
678
+ filter(map_lgl(.data $ f , ~ identical(.f , .x )))
679
+ if (nrow(f_info ) == 0L ) {
662
680
# `f` is from somewhere else and not supported
663
681
cli_abort(
664
682
c(
@@ -672,6 +690,43 @@ epi_slide_opt <- function(
672
690
epiprocess__f = .f
673
691
)
674
692
}
693
+ f_from_package <- f_info $ package
694
+
695
+ assert_string(.prefix , null.ok = TRUE )
696
+ assert_string(.suffix , null.ok = TRUE )
697
+ assert_character(.new_col_names , len = length(col_names_chr ), null.ok = TRUE )
698
+ if ((! is.null(.prefix ) || ! is.null(.suffix )) && ! is.null(.new_col_names )) {
699
+ cli_abort(
700
+ " Can't use both .prefix/.suffix and .new_col_names at the same time."
701
+ )
702
+ }
703
+ if (is.null(.prefix ) && is.null(.suffix ) && is.null(.new_col_names )) {
704
+ .suffix <- " _{.window_size}{.time_unit}{.f_abbr}"
705
+ }
706
+ if (! is.null(.prefix ) || ! is.null(.suffix )) {
707
+ .prefix <- .prefix %|| % " "
708
+ .suffix <- .suffix %|| % " "
709
+ glue_env <- rlang :: env(
710
+ .window_size = .window_size , # FIXME typing
711
+ .time_unit = " d" , # FIXME
712
+ .f_abbr = f_info $ abbr ,
713
+ quo_get_env(col_names_quo )
714
+ )
715
+ .new_col_names <- unclass(
716
+ glue(.prefix , .envir = glue_env ) +
717
+ col_names_chr +
718
+ glue(.suffix , .envir = glue_env )
719
+ )
720
+ } else {
721
+ # `.new_col_names` was provided by user; we don't need to do anything.
722
+ }
723
+ if (any(.new_col_names %in% names(.x ))) {
724
+ cli_abort(c(
725
+ " Naming conflict between new columns and existing columns" ,
726
+ " x" = " Overlapping names: {format_varnames(intersect(.new_col_names, names(.x)))}"
727
+ ))
728
+ }
729
+ result_col_names <- .new_col_names
675
730
676
731
user_provided_rtvs <- ! is.null(.ref_time_values )
677
732
if (! user_provided_rtvs ) {
@@ -708,16 +763,6 @@ epi_slide_opt <- function(
708
763
pad_early_dates <- date_seq_list $ pad_early_dates
709
764
pad_late_dates <- date_seq_list $ pad_late_dates
710
765
711
- # The position of a given column can be differ between input `.x` and
712
- # `.data_group` since the grouping step by default drops grouping columns.
713
- # To avoid rerunning `eval_select` for every `.data_group`, convert
714
- # positions of user-provided `col_names` into string column names. We avoid
715
- # using `names(pos)` directly for robustness and in case we later want to
716
- # allow users to rename fields via tidyselection.
717
- pos <- eval_select(enquo(.col_names ), data = .x , allow_rename = FALSE )
718
- col_names_chr <- names(.x )[pos ]
719
- # Always rename results to "slide_value_<original column name>".
720
- result_col_names <- paste0(" slide_value_" , col_names_chr )
721
766
slide_one_grp <- function (.data_group , .group_key , ... ) {
722
767
missing_times <- all_dates [! (all_dates %in% .data_group $ time_value )]
723
768
# `frollmean` requires a full window to compute a result. Add NA values
0 commit comments