Skip to content

Commit 0628cde

Browse files
committed
wip: rework slide window args
1 parent 871946f commit 0628cde

File tree

7 files changed

+82
-66
lines changed

7 files changed

+82
-66
lines changed

R/autoplot.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ autoplot.epi_df <- function(
4747
.facet_by = c(".response", "other_keys", "all_keys", "geo_value", "all", "none"),
4848
.base_color = "#3A448F",
4949
.max_facets = Inf) {
50-
.color_by <- match.arg(.color_by)
51-
.facet_by <- match.arg(.facet_by)
50+
.color_by <- rlang::match_arg(.color_by)
51+
.facet_by <- rlang::match_arg(.facet_by)
5252

5353
assert(anyInfinite(.max_facets), checkInt(.max_facets), combine = "or")
5454
assert_character(.base_color, len = 1)

R/correlation.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ epi_cor <- function(x, var1, var2, dt1 = 0, dt2 = 0, shift_by = geo_value, # nol
9999
shift_by <- syms(names(eval_select(enquo(shift_by), x)))
100100

101101
# Which method?
102-
method <- match.arg(method)
102+
method <- rlang::match_arg(method)
103103

104104
# Perform time shifts, then compute appropriate correlations and return
105105
return(x %>%

R/growth_rate.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ growth_rate <- function(x = seq_along(y), y, x0 = x,
120120
# Check x, y, x0
121121
if (length(x) != length(y)) cli_abort("`x` and `y` must have the same length.")
122122
if (!all(x0 %in% x)) cli_abort("`x0` must be a subset of `x`.")
123-
method <- match.arg(method)
123+
method <- rlang::match_arg(method)
124124

125125
# Arrange in increasing order of x
126126
o <- order(x)

R/outliers.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ detect_outlr <- function(x = seq_along(y), y,
8989
),
9090
combiner = c("median", "mean", "none")) {
9191
# Validate combiner
92-
combiner <- match.arg(combiner)
92+
combiner <- rlang::match_arg(combiner)
9393

9494
# Validate that x contains all distinct values
9595
if (any(duplicated(x))) {

R/slide.R

Lines changed: 58 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,10 @@
2121
#' If `f` is missing, then `...` will specify the computation.
2222
#' @param ... Additional arguments to pass to the function or formula specified
2323
#' via `f`. Alternatively, if `f` is missing, then the `...` is interpreted as
24-
#' a ["data-masking"][rlang::args_data_masking] expression or expressions for
25-
#' tidy evaluation; in addition to referring columns directly by name, the
26-
#' expressions have access to `.data` and `.env` pronouns as in `dplyr` verbs,
27-
#' and can also refer to `.x`, `.group_key`, and `.ref_time_value`. See
28-
#' details.
29-
#' @param new_col_name String indicating the name of the new column that will
30-
#' contain the derivative values. The default is "slide_value" unless your
31-
#' slide computations output data frames, in which case they will be unpacked
32-
#' into the constituent columns and those names used. Note that setting
33-
#' `new_col_name` equal to an existing column name will overwrite this column.
24+
#' an expression for tidy evaluation; in addition to referring to columns
25+
#' directly by name, the expression has access to `.data` and `.env` pronouns
26+
#' as in `dplyr` verbs, and can also refer to `.x`, `.group_key`, and
27+
#' `.ref_time_value`. See details.
3428
#'
3529
#' @template basic-slide-details
3630
#'
@@ -85,63 +79,85 @@
8579
#' before = 1, as_list_col = TRUE
8680
#' ) %>%
8781
#' ungroup()
88-
epi_slide <- function(x, f, ..., before = NULL, after = NULL, ref_time_values = NULL,
89-
new_col_name = NULL, all_rows = FALSE,
90-
as_list_col = deprecated(), names_sep = deprecated()) {
82+
epi_slide <- function(
83+
x, f, ...,
84+
.window_size = 0, .align = c("right", "center", "left"), .ref_time_values = NULL, .all_rows = FALSE) {
85+
86+
if (any(map(c(n, before, after, ref_time_values, new_col_name, as_list_col, names_sep, all_rows), Negate(is.null)))) {
87+
cli_abort(
88+
"epi_slide: deprecated arguments `n`, `before`, `after`, `ref_time_values`, `new_col_name`, `as_list_col`,
89+
`names_sep`, and `all_rows` have been removed. Please use `.n`, `.align`, `.ref_time_values`,
90+
`.new_col_name`, `.as_list_col`, and `.names_sep` instead."
91+
)
92+
}
93+
9194
assert_class(x, "epi_df")
9295

9396
if (nrow(x) == 0L) {
9497
return(x)
9598
}
9699

97-
if (is.null(ref_time_values)) {
98-
ref_time_values <- unique(x$time_value)
100+
if (is.null(.ref_time_values)) {
101+
.ref_time_values <- unique(x$time_value)
99102
} else {
100-
assert_numeric(ref_time_values, min.len = 1L, null.ok = FALSE, any.missing = FALSE)
101-
if (!test_subset(ref_time_values, unique(x$time_value))) {
103+
assert_numeric(.ref_time_values, min.len = 1L, null.ok = FALSE, any.missing = FALSE)
104+
if (!test_subset(.ref_time_values, unique(x$time_value))) {
102105
cli_abort(
103106
"`ref_time_values` must be a unique subset of the time values in `x`.",
104107
class = "epi_slide__invalid_ref_time_values"
105108
)
106109
}
107-
if (anyDuplicated(ref_time_values) != 0L) {
110+
111+
if (anyDuplicated(.ref_time_values) != 0L) {
108112
cli_abort(
109-
"`ref_time_values` must not contain any duplicates; use `unique` if appropriate.",
113+
"`.ref_time_values` must not contain any duplicates; use `unique` if appropriate.",
110114
class = "epi_slide__invalid_ref_time_values"
111115
)
112116
}
113117
}
114-
ref_time_values <- sort(ref_time_values)
118+
.ref_time_values <- sort(.ref_time_values)
115119

116-
# Handle defaults for before/after
117-
time_type <- attr(x, "metadata")$time_type
118-
if (is.null(before) && !is.null(after)) {
119-
if (inherits(after, "difftime")) {
120-
before <- as.difftime(0, units = units(after))
121-
} else {
122-
before <- 0
123-
}
120+
if (!is.null(before) || !is.null(after)) {
121+
cli_abort("`before` and `after` are deprecated for `epi_slide`. Use `n` instead.")
124122
}
125-
if (is.null(after) && !is.null(before)) {
126-
if (inherits(before, "difftime")) {
127-
after <- as.difftime(0, units = units(before))
128-
} else {
129-
if (identical(before, Inf) && time_type %in% c("day", "week")) {
123+
124+
# Handle window arguments
125+
align <- rlang::arg_match(.align)
126+
time_type <- attr(x, "metadata")$time_type
127+
validate_slide_window_arg(.window_size, time_type)
128+
if (identical(.window_size, Inf)) {
129+
if (align == "right") {
130+
before <- Inf
131+
if (time_type %in% c("day", "week")) {
130132
after <- as.difftime(0, units = glue::glue("{time_type}s"))
131133
} else {
132134
after <- 0
133135
}
136+
} else {
137+
cli_abort(
138+
"`epi_slide`: center and left alignment are not supported with an infinite window size."
139+
)
140+
}
141+
} else {
142+
if (align == "right") {
143+
before <- .window_size - 1
144+
after <- 0
145+
} else if (align == "center") {
146+
# For n = 5, before = 2, after = 2. For n = 4, before = 2, after = 1.
147+
before <- floor(.window_size / 2)
148+
after <- .window_size - before - 1
149+
} else if (align == "left") {
150+
before <- 0
151+
after <- .window_size - 1
134152
}
135153
}
136-
validate_slide_window_arg(before, time_type)
137-
validate_slide_window_arg(after, time_type, allow_inf = FALSE)
138154

139155
# Arrange by increasing time_value
140156
x <- arrange(x, .data$time_value)
141157

142158
# Now set up starts and stops for sliding/hopping
143-
starts <- ref_time_values - before
144-
stops <- ref_time_values + after
159+
starts <- .ref_time_values - before
160+
stops <- .ref_time_values + after
145161

146162
# If `f` is missing, interpret ... as an expression for tidy evaluation
147163
if (missing(f)) {
@@ -220,6 +236,7 @@ epi_slide <- function(x, f, ..., before = NULL, after = NULL, ref_time_values =
220236
return(f_wrapper)
221237
}
222238

239+
223240
# Computation for one group, all time values
224241
slide_one_grp <- function(.data_group,
225242
.group_key, # see `?group_modify`
@@ -282,6 +299,7 @@ epi_slide <- function(x, f, ..., before = NULL, after = NULL, ref_time_values =
282299

283300
slide_values <- vctrs::list_unchop(slide_values_list)
284301

302+
285303
if (
286304
all(purrr::map_int(slide_values_list, vctrs::vec_size) == 1L) &&
287305
length(slide_values_list) != 0L
@@ -333,12 +351,13 @@ epi_slide <- function(x, f, ..., before = NULL, after = NULL, ref_time_values =
333351
f_factory = f_wrapper_factory,
334352
starts = starts,
335353
stops = stops,
336-
ref_time_values = ref_time_values,
337-
all_rows = all_rows,
354+
ref_time_values = .ref_time_values,
355+
all_rows = .all_rows,
338356
new_col_name = new_col_name,
339357
.keep = FALSE
340358
)
341359

360+
342361
return(x)
343362
}
344363

man-roxygen/basic-slide-params.R

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,30 @@
11
#' @param x The `epi_df` object under consideration, [grouped][dplyr::group_by]
22
#' or ungrouped. If ungrouped, all data in `x` will be treated as part of a
33
#' single data group.
4-
#' @param before,after How far `before` and `after` each `ref_time_value` should
5-
#' the sliding window extend? At least one of these two arguments must be
6-
#' provided; the other's default will be 0. The accepted values for these
7-
#' depend on the type of the `time_value` column:
4+
#' @param .window_size The size of the sliding window. By default, this is 0,
5+
#' meaning that only the current ref_time_value is included. The accepted values
6+
#' here depend on the `time_value` column:
87
#'
9-
#' - if it is a Date and the cadence is daily, then they can be integers
10-
#' (which will be interpreted in units of days) or difftimes with units
8+
#' - if time_type is Date and the cadence is daily, then `.n` can be an integer
9+
#' (which will be interpreted in units of days) or a difftime with units
1110
#' "days"
12-
#' - if it is a Date and the cadence is weekly, then they must be difftimes
11+
#' - if time_type is Date and the cadence is weekly, then `.n` must be a difftime
1312
#' with units "weeks"
14-
#' - if it is an integer, then they must be integers
13+
#' - if time_type is an integer, then `.n` must be an integer
1514
#'
16-
#' Endpoints of the window are inclusive. Common settings:
17-
#'
18-
#' - For trailing/right-aligned windows from `ref_time_value - k` to
19-
#' `ref_time_value`: either pass `before=k` by itself, or pass `before=k,
20-
#' after=0`.
21-
#' - For center-aligned windows from `ref_time_value - k` to
22-
#' `ref_time_value + k`: pass `before=k, after=k`.
23-
#' - For leading/left-aligned windows from `ref_time_value` to
24-
#' `ref_time_value + k`: either pass pass `after=k` by itself,
25-
#' or pass `before=0, after=k`.
26-
#'
27-
#' See "Details:" on how missing rows are handled within the window.
28-
#' @param ref_time_values Time values for sliding computations, meaning, each
15+
#' @param .align The alignment of the sliding window. If `right` (default), then
16+
#' the window has its end at the reference time; if `center`, then the window is
17+
#' centered at the reference time; if `left`, then the window has its start at
18+
#' the reference time. If the alignment is `center` and the window size is odd,
19+
#' then the window will have floor(window_size/2) points before and after the
20+
#' reference time. If the window size is even, then the window will be
21+
#' asymmetric and have one less value on the right side of the reference time.
22+
#' @param before,after Deprecated. Use `.n` instead.
23+
#' @param .ref_time_values Time values for sliding computations, meaning, each
2924
#' element of this vector serves as the reference time point for one sliding
3025
#' window. If missing, then this will be set to all unique time values in the
3126
#' underlying data table, by default.
32-
#' @param all_rows If `all_rows = TRUE`, then all rows of `x` will be kept in
27+
#' @param .all_rows If `all_rows = TRUE`, then all rows of `x` will be kept in
3328
#' the output even with `ref_time_values` provided, with some type of missing
3429
#' value marker for the slide computation output column(s) for `time_value`s
3530
#' outside `ref_time_values`; otherwise, there will be one row for each row in

man/epi_slide.Rd

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)