@@ -168,9 +168,12 @@ across_ish_names_info <- function(.x, time_type, col_names_quo, .f_namer,
168168}
169169
170170epi_slide_opt_one_epikey <- function (inp_tbl ,
171- f_dots_baked , f_from_package , before , after , unit_step , time_type ,
171+ f_dots_baked , f_from_package ,
172+ before_steps , after_steps , unit_step , time_type ,
172173 out_filter_time_range , out_filter_time_set ,
173174 in_colnames , out_colnames ) {
175+ # TODO rename function, reorder args, roxygen2
176+ #
174177 # TODO try converting time values to reals, do work on reals, convert back at very end?
175178 #
176179 # TODO loosen restrictions here. each filter optional?
@@ -187,8 +190,14 @@ epi_slide_opt_one_epikey <- function(inp_tbl,
187190 } else {
188191 cli_abort(" Exactly one of `out_filter_time_range` and `out_filter_time_set` must be non-`NULL`." )
189192 }
190- slide_t_min <- time_minus_slide_window_arg(out_t_min , before , time_type , min(inp_tbl $ time_value ))
191- slide_t_max <- time_plus_slide_window_arg(out_t_max , after , time_type )
193+ if (before_steps == Inf ) {
194+ slide_t_min <- min(inp_tbl $ time_value )
195+ slide_start_padding_n <- time_minus_time_in_n_steps(out_t_min , slide_t_min , time_type )
196+ } else {
197+ slide_t_min <- out_t_min - before_steps * unit_step
198+ slide_start_padding_n <- before_steps # perf: avoid time_minus_time_in_n_steps
199+ }
200+ slide_t_max <- out_t_max + after_steps * unit_step
192201 slide_nrow <- time_delta_to_n_steps(slide_t_max - slide_t_min , time_type ) + 1L
193202 slide_time_values <- slide_t_min + 0L : (slide_nrow - 1L ) * unit_step
194203 slide_inp_backrefs <- vec_match(slide_time_values , inp_tbl $ time_value )
@@ -200,37 +209,41 @@ epi_slide_opt_one_epikey <- function(inp_tbl,
200209 # try removing time_value column before slice?
201210 slide $ time_value <- slide_time_values
202211 if (f_from_package == " data.table" ) {
203- if (before == Inf ) {
212+ if (before_steps == Inf ) {
204213 slide [, out_colnames ] <-
205214 f_dots_baked(slide [, in_colnames ], seq_len(slide_nrow ), adaptive = TRUE )
206215 } else {
207- out_cols <- f_dots_baked(slide [, in_colnames ], before + after + 1L )
208- if (after != 0L ) {
216+ out_cols <- f_dots_baked(slide [, in_colnames ], before_steps + after_steps + 1L )
217+ if (after_steps != 0L ) {
209218 # Shift an appropriate amount of NA padding from the start to the end.
210219 # (This padding will later be cut off when we filter down to the
211220 # original time_values.)
212221 out_cols <- lapply(out_cols , function (out_col ) {
213- c(out_col [(after + 1L ): length(out_col )], rep(NA , after ))
222+ c(out_col [(after_steps + 1L ): length(out_col )], rep(NA , after_steps ))
214223 })
215224 }
216225 slide [, out_colnames ] <- out_cols
217226 }
218227 } else if (f_from_package == " slider" ) {
219228 for (col_i in seq_along(in_colnames )) {
220- slide [[out_colnames [[col_i ]]]] <- f_dots_baked(slide [[in_colnames [[col_i ]]]], before = before , after = after )
229+ slide [[out_colnames [[col_i ]]]] <- f_dots_baked(slide [[in_colnames [[col_i ]]]], before = before_steps , after = after_steps )
221230 }
222231 } else {
223232 cli_abort(
224233 " epiprocess internal error: `f_from_package` was {format_chr_deparse(f_from_package)}, which is unsupported" ,
225234 class = " epiprocess__epi_slide_opt_archive__f_from_package_invalid"
226235 )
227236 }
237+ # We should filter down the slide time values to ones in the input time values
238+ # when preparing the output:
228239 rows_should_keep1 <- ! is.na(slide_inp_backrefs )
229- rows_should_keep2 <- switch (
230- out_filter_time_style ,
240+ # We also need to apply the out_filter.
241+ #
242+ # TODO comments + test vs. just using inequality
243+ rows_should_keep2 <- switch (out_filter_time_style ,
231244 range = vec_rep_each(
232245 c(FALSE , TRUE , FALSE ),
233- c(before , slide_nrow - before - after , after ),
246+ c(slide_start_padding_n , slide_nrow - slide_start_padding_n - after_steps , after_steps ),
234247 ),
235248 set = vec_in(slide_time_values , out_time_values )
236249 )
@@ -493,12 +506,15 @@ epi_slide_opt.epi_df <- function(.x, .col_names, .f, ...,
493506 .align <- rlang :: arg_match(.align )
494507 time_type <- attr(.x , " metadata" )$ time_type
495508 if (is.null(.window_size )) {
496- cli_abort(" epi_slide_opt: `.window_size` must be specified." )
509+ cli_abort(
510+ " epi_slide_opt: `.window_size` must be specified." ,
511+ class = " epiprocess__epi_slide_opt__window_size_missing"
512+ )
497513 }
498514 validate_slide_window_arg(.window_size , time_type )
499515 window_args <- get_before_after_from_window(.window_size , .align , time_type )
500- before <- time_delta_to_n_steps(window_args $ before , time_type )
501- after <- time_delta_to_n_steps(window_args $ after , time_type )
516+ before_steps <- time_delta_to_n_steps(window_args $ before , time_type )
517+ after_steps <- time_delta_to_n_steps(window_args $ after , time_type )
502518 unit_step <- unit_time_delta(time_type , format = " fast" )
503519
504520 # Handle output naming:
@@ -520,7 +536,7 @@ epi_slide_opt.epi_df <- function(.x, .col_names, .f, ...,
520536
521537 result <- .x %> %
522538 group_modify(function (grp_data , grp_key ) {
523- epi_slide_opt_one_epikey(grp_data , f_dots_baked , f_from_package , before , after , unit_step , time_type , NULL , ref_time_values , names_info $ input_col_names , names_info $ output_col_names )
539+ epi_slide_opt_one_epikey(grp_data , f_dots_baked , f_from_package , before_steps , after_steps , unit_step , time_type , NULL , ref_time_values , names_info $ input_col_names , names_info $ output_col_names )
524540 }) %> %
525541 arrange_col_canonical()
526542
0 commit comments