@@ -168,9 +168,12 @@ across_ish_names_info <- function(.x, time_type, col_names_quo, .f_namer,
168
168
}
169
169
170
170
epi_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 ,
172
173
out_filter_time_range , out_filter_time_set ,
173
174
in_colnames , out_colnames ) {
175
+ # TODO rename function, reorder args, roxygen2
176
+ #
174
177
# TODO try converting time values to reals, do work on reals, convert back at very end?
175
178
#
176
179
# TODO loosen restrictions here. each filter optional?
@@ -187,8 +190,14 @@ epi_slide_opt_one_epikey <- function(inp_tbl,
187
190
} else {
188
191
cli_abort(" Exactly one of `out_filter_time_range` and `out_filter_time_set` must be non-`NULL`." )
189
192
}
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
192
201
slide_nrow <- time_delta_to_n_steps(slide_t_max - slide_t_min , time_type ) + 1L
193
202
slide_time_values <- slide_t_min + 0L : (slide_nrow - 1L ) * unit_step
194
203
slide_inp_backrefs <- vec_match(slide_time_values , inp_tbl $ time_value )
@@ -200,37 +209,41 @@ epi_slide_opt_one_epikey <- function(inp_tbl,
200
209
# try removing time_value column before slice?
201
210
slide $ time_value <- slide_time_values
202
211
if (f_from_package == " data.table" ) {
203
- if (before == Inf ) {
212
+ if (before_steps == Inf ) {
204
213
slide [, out_colnames ] <-
205
214
f_dots_baked(slide [, in_colnames ], seq_len(slide_nrow ), adaptive = TRUE )
206
215
} 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 ) {
209
218
# Shift an appropriate amount of NA padding from the start to the end.
210
219
# (This padding will later be cut off when we filter down to the
211
220
# original time_values.)
212
221
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 ))
214
223
})
215
224
}
216
225
slide [, out_colnames ] <- out_cols
217
226
}
218
227
} else if (f_from_package == " slider" ) {
219
228
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 )
221
230
}
222
231
} else {
223
232
cli_abort(
224
233
" epiprocess internal error: `f_from_package` was {format_chr_deparse(f_from_package)}, which is unsupported" ,
225
234
class = " epiprocess__epi_slide_opt_archive__f_from_package_invalid"
226
235
)
227
236
}
237
+ # We should filter down the slide time values to ones in the input time values
238
+ # when preparing the output:
228
239
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 ,
231
244
range = vec_rep_each(
232
245
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 ),
234
247
),
235
248
set = vec_in(slide_time_values , out_time_values )
236
249
)
@@ -493,12 +506,15 @@ epi_slide_opt.epi_df <- function(.x, .col_names, .f, ...,
493
506
.align <- rlang :: arg_match(.align )
494
507
time_type <- attr(.x , " metadata" )$ time_type
495
508
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
+ )
497
513
}
498
514
validate_slide_window_arg(.window_size , time_type )
499
515
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 )
502
518
unit_step <- unit_time_delta(time_type , format = " fast" )
503
519
504
520
# Handle output naming:
@@ -520,7 +536,7 @@ epi_slide_opt.epi_df <- function(.x, .col_names, .f, ...,
520
536
521
537
result <- .x %> %
522
538
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 )
524
540
}) %> %
525
541
arrange_col_canonical()
526
542
0 commit comments