Skip to content

Commit 00e967d

Browse files
committed
move ref_time_value calculation to a wrapper in epi_slide
Drop `calc_ref_time_value` and `before` args to `as_slide_computation`; they were only used to calculate `.ref_time_value` for `epi_slide` computations.
1 parent d0acab4 commit 00e967d

File tree

3 files changed

+44
-85
lines changed

3 files changed

+44
-85
lines changed

R/grouped_epi_archive.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ grouped_epi_archive =
307307
... = missing_arg()
308308
}
309309

310-
f = as_slide_computation(f, calc_ref_time_value = FALSE, ...)
310+
f = as_slide_computation(f, ...)
311311
x = purrr::map_dfr(ref_time_values, function(ref_time_value) {
312312
# Ungrouped as-of data; `epi_df` if `all_versions` is `FALSE`,
313313
# `epi_archive` if `all_versions` is `TRUE`:

R/slide.R

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,10 +366,18 @@ epi_slide = function(x, f, ..., before, after, ref_time_values,
366366
... = missing_arg()
367367
}
368368

369-
f = as_slide_computation(f, calc_ref_time_value = TRUE, before = before, ...)
369+
f = as_slide_computation(f, ...)
370+
# Create a wrapper that calculates and passes `.ref_time_value` to the
371+
# computation.
372+
f_wrapper = function(.x, .group_key, ...) {
373+
.ref_time_value = min(.x$time_value) + before
374+
.x <- .x[.x$.real,]
375+
.x$.real <- NULL
376+
f(.x, .group_key, .ref_time_value, ...)
377+
}
370378
x = x %>%
371379
group_modify(slide_one_grp,
372-
f = f, ...,
380+
f = f_wrapper, ...,
373381
starts = starts,
374382
stops = stops,
375383
time_values = ref_time_values,

R/utils.R

Lines changed: 33 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -200,11 +200,8 @@ assert_sufficient_f_args <- function(f, ...) {
200200
#'
201201
#' @param .f A function, one-sided formula, or quosure.
202202
#'
203-
#' If a **function** and `calc_ref_time_value` is `FALSE`, the function is
204-
#' returned as-is, with no modifications. If `calc_ref_time_value` is
205-
#' `TRUE`, a function wrapping the original function is returned. The
206-
#' wrapper calculates `.ref_time_value` based on the input data and passes
207-
#' it to the original function.
203+
#' If a **function**, the function is returned as-is, with no
204+
#' modifications.
208205
#'
209206
#' If a **formula**, e.g. `~ mean(.x$cases)`, it is converted to a function
210207
#' with up to three arguments: `.x` (single argument), or `.x` and `.y`
@@ -218,23 +215,8 @@ assert_sufficient_f_args <- function(f, ...) {
218215
#' If a **quosure**, in the case that `f` was not provided to the parent
219216
#' `epi[x]_slide` call and the `...` is interpreted as an expression for
220217
#' tidy evaluation, it is evaluated within a wrapper function. The wrapper
221-
#' sets up object access via a data mask. `.ref_time_value` is calculated
222-
#' depending on the `cal_ref_time_value` setting.
223-
#'
224-
#' @param before How far `before` each `ref_time_value` the sliding window
225-
#' should extend, as specified in the parent `epi[x]_slide` call. Must be a
226-
#' single, non-`NA`, non-negative,[integer-compatible]
227-
#' [vctrs::vec_cast] number of time steps. Used only when
228-
#' `calc_ref_time_value` is `TRUE`.
229-
#' @param calc_ref_time_value Boolean indicating whether the computation
230-
#' function should include a step to calculate `ref_time_value` based on the
231-
#' contents of the group data `.x`. This is used in `epi_slide`. When this
232-
#' flag is `FALSE`, as is the default, the resulting computation takes the
233-
#' three standard arguments, group data, group key(s), and reference time
234-
#' value, plus any extra arguments. When this flag is `TRUE`, the resulting
235-
#' computation only takes two of the standard arguments, group data and
236-
#' group key(s), plus any extra arguments. The `ref_time_value` argument is
237-
#' unnecessary since its value is being calculated within the computation.
218+
#' sets up object access via a data mask.
219+
#'
238220
#' @param ... Additional arguments to pass to the function or formula
239221
#' specified via `x`. If `x` is a quosure, any arguments passed via `...`
240222
#' will be ignored.
@@ -254,33 +236,13 @@ assert_sufficient_f_args <- function(f, ...) {
254236
#'
255237
#' @noRd
256238
as_slide_computation <- function(.f,
257-
before,
258-
calc_ref_time_value = FALSE,
259239
...,
260240
arg = caller_arg(.f),
261241
call = caller_env()) {
262242
# A quosure is a type of formula, so be careful with the order and contents
263243
# of the conditional logic here.
264244
if (is_quosure(.f)) {
265-
if (calc_ref_time_value) {
266-
f_wrapper = function(.x, .group_key, ...) {
267-
.ref_time_value = min(.x$time_value) + before
268-
.x <- .x[.x$.real,]
269-
.x$.real <- NULL
270-
271-
data_env = rlang::as_environment(.x)
272-
data_mask = rlang::new_data_mask(bottom = data_env, top = data_env)
273-
data_mask$.data <- rlang::as_data_pronoun(data_mask)
274-
# Also install `.x` directly.
275-
data_mask$.x = .x
276-
data_mask$.group_key = .group_key
277-
data_mask$.ref_time_value = .ref_time_value
278-
rlang::eval_tidy(.f, data_mask)
279-
}
280-
return(f_wrapper)
281-
}
282-
283-
f_wrapper = function(.x, .group_key, .ref_time_value, ...) {
245+
fn = function(.x, .group_key, .ref_time_value, ...) {
284246
# Convert to environment to standardize between tibble and R6
285247
# based inputs. In both cases, we should get a simple
286248
# environment with the empty environment as its parent.
@@ -294,52 +256,41 @@ as_slide_computation <- function(.f,
294256
data_mask$.ref_time_value = .ref_time_value
295257
rlang::eval_tidy(.f, data_mask)
296258
}
297-
return(f_wrapper)
298-
}
299-
300-
if (is_function(.f) || is_formula(.f)) {
301-
if (is_function(.f)) {
302-
# Check that `f` takes enough args
303-
assert_sufficient_f_args(.f, ...)
304-
fn <- .f
305-
}
306259

307-
if (is_formula(.f)) {
308-
if (length(.f) > 2) {
309-
Abort(sprintf("%s must be a one-sided formula", arg),
310-
class = "epiprocess__as_slide_computation__formula_is_twosided",
311-
epiprocess__f = .f,
312-
call = call)
313-
}
260+
return(fn)
261+
}
314262

315-
env <- f_env(.f)
316-
if (!is_environment(env)) {
317-
Abort("Formula must carry an environment.",
318-
class = "epiprocess__as_slide_computation__formula_has_no_env",
319-
epiprocess__f = .f,
320-
epiprocess__f_env = env,
321-
arg = arg, call = call)
322-
}
263+
if (is_function(.f)) {
264+
# Check that `f` takes enough args
265+
assert_sufficient_f_args(.f, ...)
266+
return(.f)
267+
}
323268

324-
args <- list(
325-
... = missing_arg(),
326-
.x = quote(..1), .y = quote(..2), .z = quote(..3),
327-
. = quote(..1), .group_key = quote(..2), .ref_time_value = quote(..3)
328-
)
329-
fn <- new_function(args, f_rhs(.f), env)
330-
fn <- structure(fn, class = c("epiprocess_slide_computation", "function"))
269+
if (is_formula(.f)) {
270+
if (length(.f) > 2) {
271+
Abort(sprintf("%s must be a one-sided formula", arg),
272+
class = "epiprocess__as_slide_computation__formula_is_twosided",
273+
epiprocess__f = .f,
274+
call = call)
331275
}
332276

333-
if (calc_ref_time_value) {
334-
f_wrapper = function(.x, .group_key, ...) {
335-
.ref_time_value = min(.x$time_value) + before
336-
.x <- .x[.x$.real,]
337-
.x$.real <- NULL
338-
fn(.x, .group_key, .ref_time_value, ...)
339-
}
340-
return(f_wrapper)
277+
env <- f_env(.f)
278+
if (!is_environment(env)) {
279+
Abort("Formula must carry an environment.",
280+
class = "epiprocess__as_slide_computation__formula_has_no_env",
281+
epiprocess__f = .f,
282+
epiprocess__f_env = env,
283+
arg = arg, call = call)
341284
}
342285

286+
args <- list(
287+
... = missing_arg(),
288+
.x = quote(..1), .y = quote(..2), .z = quote(..3),
289+
. = quote(..1), .group_key = quote(..2), .ref_time_value = quote(..3)
290+
)
291+
fn <- new_function(args, f_rhs(.f), env)
292+
fn <- structure(fn, class = c("epiprocess_slide_computation", "function"))
293+
343294
return(fn)
344295
}
345296

0 commit comments

Comments
 (0)