Skip to content

Commit

Permalink
Merge upstream changes & resolve DESCRIPTION, NEWS.md
Browse files Browse the repository at this point in the history
  • Loading branch information
brookslogan committed Oct 2, 2024
2 parents e5adcbd + 493a24a commit 793c9f7
Show file tree
Hide file tree
Showing 13 changed files with 142 additions and 98 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Type: Package
Package: epiprocess
Title: Tools for basic signal processing in epidemiology
Version: 0.10.1
Version: 0.9.3
Authors@R: c(
person("Jacob", "Bien", role = "ctb"),
person("Logan", "Brooks", , "[email protected]", role = c("aut", "cre")),
Expand Down
8 changes: 8 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,18 @@ Pre-1.0.0 numbering scheme: 0.x will indicate releases, while 0.x.y will indicat

# epiprocess 0.10

## Breaking changes

- Removed `.window_size = 1` default from `epi_slide_{mean,sum,opt}`; this
argument is now mandatory, and should nearly always be greater than 1 except
for testing purposes.

## Improvements

- `epi_slide` and `epix_slide` now provide some hints if you forget a `~` when
using a formula to specify the slide computation, and other bits of forgotten
syntax.
- Improved validation of `.window_size` arguments.

# epiprocess 0.9

Expand Down
2 changes: 1 addition & 1 deletion R/archive.R
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#' @noRd
validate_version_bound <- function(version_bound, x, na_ok = FALSE,
version_bound_arg = rlang::caller_arg(version_bound),
x_arg = rlang::caller_arg(version_bound)) {
x_arg = rlang::caller_arg(x)) {
if (is.null(version_bound)) {
cli_abort(
"{version_bound_arg} cannot be NULL",
Expand Down
60 changes: 15 additions & 45 deletions R/slide.R
Original file line number Diff line number Diff line change
Expand Up @@ -578,7 +578,7 @@ get_before_after_from_window <- function(window_size, align, time_type) {
#' ungroup()
epi_slide_opt <- function(
.x, .col_names, .f, ...,
.window_size = 1, .align = c("right", "center", "left"),
.window_size = NULL, .align = c("right", "center", "left"),
.ref_time_values = NULL, .all_rows = FALSE) {
assert_class(.x, "epi_df")

Expand Down Expand Up @@ -680,46 +680,16 @@ epi_slide_opt <- function(
ref_time_values <- sort(.ref_time_values)

# Handle window arguments
align <- rlang::arg_match(.align)
.align <- rlang::arg_match(.align)
time_type <- attr(.x, "metadata")$time_type
validate_slide_window_arg(.window_size, time_type)
if (identical(.window_size, Inf)) {
if (align == "right") {
before <- Inf
if (time_type %in% c("day", "week")) {
after <- as.difftime(0, units = glue::glue("{time_type}s"))
} else {
after <- 0
}
} else {
cli_abort(
"`epi_slide`: center and left alignment are not supported with an infinite window size."
)
}
} else {
if (align == "right") {
before <- .window_size - 1
if (time_type %in% c("day", "week")) {
after <- as.difftime(0, units = glue::glue("{time_type}s"))
} else {
after <- 0
}
} else if (align == "center") {
# For .window_size = 5, before = 2, after = 2. For .window_size = 4, before = 2, after = 1.
before <- floor(.window_size / 2)
after <- .window_size - before - 1
} else if (align == "left") {
if (time_type %in% c("day", "week")) {
before <- as.difftime(0, units = glue::glue("{time_type}s"))
} else {
before <- 0
}
after <- .window_size - 1
}
if (is.null(.window_size)) {
cli_abort("epi_slide_opt: `.window_size` must be specified.")
}
validate_slide_window_arg(.window_size, time_type)
window_args <- get_before_after_from_window(.window_size, .align, time_type)

# Make a complete date sequence between min(.x$time_value) and max(.x$time_value).
date_seq_list <- full_date_seq(.x, before, after, time_type)
date_seq_list <- full_date_seq(.x, window_args$before, window_args$after, time_type)
all_dates <- date_seq_list$all_dates
pad_early_dates <- date_seq_list$pad_early_dates
pad_late_dates <- date_seq_list$pad_late_dates
Expand Down Expand Up @@ -788,16 +758,16 @@ epi_slide_opt <- function(
# `before` and `after` params. Right-aligned `frollmean` results'
# `ref_time_value`s will be `after` timesteps ahead of where they should
# be; shift results to the left by `after` timesteps.
if (before != Inf) {
window_size <- before + after + 1L
if (window_args$before != Inf) {
window_size <- window_args$before + window_args$after + 1L
roll_output <- .f(x = .data_group[, col_names_chr], n = window_size, ...)
} else {
window_size <- list(seq_along(.data_group$time_value))
roll_output <- .f(x = .data_group[, col_names_chr], n = window_size, adaptive = TRUE, ...)
}
if (after >= 1) {
if (window_args$after >= 1) {
.data_group[, result_col_names] <- purrr::map(roll_output, function(.x) {
c(.x[(after + 1L):length(.x)], rep(NA, after))
c(.x[(window_args$after + 1L):length(.x)], rep(NA, window_args$after))
})
} else {
.data_group[, result_col_names] <- roll_output
Expand All @@ -807,8 +777,8 @@ epi_slide_opt <- function(
for (i in seq_along(col_names_chr)) {
.data_group[, result_col_names[i]] <- .f(
x = .data_group[[col_names_chr[i]]],
before = as.numeric(before),
after = as.numeric(after),
before = as.numeric(window_args$before),
after = as.numeric(window_args$after),
...
)
}
Expand Down Expand Up @@ -904,7 +874,7 @@ epi_slide_opt <- function(
#' ungroup()
epi_slide_mean <- function(
.x, .col_names, ...,
.window_size = 1, .align = c("right", "center", "left"),
.window_size = NULL, .align = c("right", "center", "left"),
.ref_time_values = NULL, .all_rows = FALSE) {
# Deprecated argument handling
provided_args <- rlang::call_args_names(rlang::call_match())
Expand Down Expand Up @@ -981,7 +951,7 @@ epi_slide_mean <- function(
#' ungroup()
epi_slide_sum <- function(
.x, .col_names, ...,
.window_size = 1, .align = c("right", "center", "left"),
.window_size = NULL, .align = c("right", "center", "left"),
.ref_time_values = NULL, .all_rows = FALSE) {
# Deprecated argument handling
provided_args <- rlang::call_args_names(rlang::call_match())
Expand Down
84 changes: 56 additions & 28 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -1003,14 +1003,28 @@ guess_period.POSIXt <- function(time_values, time_values_arg = rlang::caller_arg
as.numeric(NextMethod(), units = "secs")
}

validate_slide_window_arg <- function(arg, time_type, lower = 1, allow_inf = TRUE, arg_name = rlang::caller_arg(arg)) {
if (!checkmate::test_scalar(arg) || arg < lower) {
cli_abort(
"Slide function expected `{arg_name}` to be a non-null, scalar integer >= {lower}.",
class = "epiprocess__validate_slide_window_arg"
)
#' Is `x` an "int" with a sensible class? TRUE/FALSE
#'
#' Like [`checkmate::test_int`] but disallowing some non-sensible classes that
#' `test_int` accepts, such as `difftime`s. We rely on [`is.numeric`] to
#' determine class appropriateness; note that `is.numeric` is NOT simply
#' checking for the class to be "numeric" (or else we'd fail on integer class).
#'
#' @param x object
#' @return Boolean
#'
#' @importFrom checkmate test_int
#' @keywords internal
test_sensible_int <- function(x, na.ok = FALSE, lower = -Inf, upper = Inf, # nolint: object_name_linter
tol = sqrt(.Machine$double.eps), null.ok = FALSE) { # nolint: object_name_linter
if (null.ok && is.null(x)) {
TRUE
} else {
is.numeric(x) && test_int(x, na.ok = na.ok, lower = lower, upper = upper, tol = tol)
}
}

validate_slide_window_arg <- function(arg, time_type, lower = 1, allow_inf = TRUE, arg_name = rlang::caller_arg(arg)) {
if (time_type == "custom") {
cli_abort(
"Unsure how to interpret slide units with a custom time type. Consider converting your time
Expand All @@ -1020,31 +1034,45 @@ validate_slide_window_arg <- function(arg, time_type, lower = 1, allow_inf = TRU
}

msg <- ""
if (!identical(arg, Inf)) {
if (time_type == "day") {
if (!test_int(arg, lower = 0L) && !(inherits(arg, "difftime") && units(arg) == "days")) {
msg <- glue::glue_collapse(c("difftime with units in days", "non-negative integer", "Inf"), " or ")
}
} else if (time_type == "week") {
if (!(inherits(arg, "difftime") && units(arg) == "weeks")) {
msg <- glue::glue_collapse(c("difftime with units in weeks", "Inf"), " or ")
}
} else if (time_type == "yearmonth") {
if (!test_int(arg, lower = 0L) || inherits(arg, "difftime")) {
msg <- glue::glue_collapse(c("non-negative integer", "Inf"), " or ")
}
} else if (time_type == "integer") {
if (!test_int(arg, lower = 0L) || inherits(arg, "difftime")) {
msg <- glue::glue_collapse(c("non-negative integer", "Inf"), " or ")
}
} else {
msg <- glue::glue_collapse(c("difftime", "non-negative integer", "Inf"), " or ")
}
inf_if_okay <- if (allow_inf) {
"Inf"
} else {
if (!allow_inf) {
msg <- glue::glue_collapse(c("a difftime", "a non-negative integer"), " or ")
character(0L)
}

# nolint start: indentation_linter.
if (time_type == "day") {
if (!(test_sensible_int(arg, lower = lower) ||
inherits(arg, "difftime") && length(arg) == 1L && units(arg) == "days" ||
allow_inf && identical(arg, Inf)
)) {
msg <- glue::glue_collapse(c("length-1 difftime with units in days", "non-negative integer", inf_if_okay), " or ")
}
} else if (time_type == "week") {
if (!(inherits(arg, "difftime") && length(arg) == 1L && units(arg) == "weeks" ||
allow_inf && identical(arg, Inf)
)) {
msg <- glue::glue_collapse(c("length-1 difftime with units in weeks", inf_if_okay), " or ")
}
} else if (time_type == "yearmonth") {
if (!(test_sensible_int(arg, lower = lower) ||
allow_inf && identical(arg, Inf)
)) {
msg <- glue::glue_collapse(c("non-negative integer", inf_if_okay), " or ")
}
} else if (time_type == "integer") {
if (!(test_sensible_int(arg, lower = lower) ||
allow_inf && identical(arg, Inf)
)) {
msg <- glue::glue_collapse(c("non-negative integer", inf_if_okay), " or ")
}
} else {
cli_abort('`epiprocess` internal error: unrecognized time_type: "{time_type}"',
class = "epiprocess__unrecognized_time_type"
)
}
# nolint end

if (msg != "") {
cli_abort(
"Slide function expected `{arg_name}` to be a {msg}.",
Expand Down
3 changes: 2 additions & 1 deletion man-roxygen/basic-slide-params.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
#' with units "days"
#' - if time_type is Date and the cadence is weekly, then `.window_size` must
#' be a difftime with units "weeks"
#' - if time_type is an integer, then `.window_size` must be an integer
#' - if time_type is an yearmonth or integer, then `.window_size` must be an
#' integer
#'
#' @param .align The alignment of the sliding window. If `right` (default), then
#' the window has its end at the reference time; if `center`, then the window is
Expand Down
3 changes: 2 additions & 1 deletion man/epi_slide.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions man/epi_slide_mean.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions man/epi_slide_opt.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions man/epi_slide_sum.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions man/test_sensible_int.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 2 additions & 10 deletions tests/testthat/test-epi_slide.R
Original file line number Diff line number Diff line change
Expand Up @@ -711,17 +711,9 @@ test_that("epi_slide_opt helper `full_date_seq` returns expected date values", {

test_that("`epi_slide_opt` errors when passed non-`data.table`, non-`slider` functions", {
reexport_frollmean <- data.table::frollmean
expect_no_error(
epi_slide_opt(
test_data,
.col_names = value, .f = reexport_frollmean
)
)
expect_no_error(epi_slide_opt(test_data, .col_names = value, .f = reexport_frollmean, .window_size = 7))
expect_error(
epi_slide_opt(
test_data,
.col_names = value, .f = mean
),
epi_slide_opt(test_data, .col_names = value, .f = mean),
class = "epiprocess__epi_slide_opt__unsupported_slide_function"
)
})
Expand Down
Loading

0 comments on commit 793c9f7

Please sign in to comment.