context("zoo") test_that("we behave similarly to zoo::rollapply", { if (!requireNamespace("zoo", quietly = TRUE)) skip("zoo not installed") library(testthat) functions <- c("mean", "median", "prod", "min", "max", "sum") x <- rnorm(50) window <- 5L run_tests <- function(data, width, ..., functions, gctorture = FALSE) { for (f in functions) { RcppRoll <- get(paste("roll", f, sep = "_"), envir = asNamespace("RcppRoll")) zoo <- zoo::rollapply(data, width, FUN = get(f), ...) if (is.matrix(zoo)) { dimnames(zoo) <- NULL } if (gctorture) gctorture(TRUE) RcppRollRes <- RcppRoll(data, width, ...) if (gctorture) gctorture(FALSE) withCallingHandlers( expect_equal(RcppRollRes, zoo), error = function(cnd) { str(list(fn = f, data = data, width = width, ...)) } ) } } run_tests(x, window, functions = functions) window <- 50L run_tests(x, window, functions = functions) window <- 1L run_tests(x, window, functions = functions) ## test against small numbers x <- rnorm(1E3) ^ 100 run_tests(x, 5L, functions = functions) ## and large numbers x <- rnorm(1E3, mean = 1E200, sd = 1E201) run_tests(x, 5L, functions = functions) ## now let's really stress it... args <- expand.grid( width = list(3L, 10L, 100L), fill = list(NA, c(-1, 0, 1)), align = list("left", "center", "right"), by = c(1L, 2L, 5L), na.rm = c(TRUE, FALSE) ) # don't use median here data <- rnorm(1E2, 100, 50) for (i in 1:nrow(args)) { run_tests(data, args$width[[i]], fill = args$fill[[i]], align = args$align[[i]], na.rm = args$na.rm[[i]], by = args$by[[i]], functions = functions) } data[sample(length(data), length(data) / 3)] <- NA for (i in 1:nrow(args)) { suppressWarnings(run_tests(data, args$width[[i]], fill = args$fill[[i]], align = args$align[[i]], na.rm = args$na.rm[[i]], by = args$by[[i]], functions = functions)) } data <- matrix(rnorm(2E2, 100, 50), nrow = 100) for (i in 1:nrow(args)) { run_tests( data, args$width[[i]], fill = args$fill[[i]], align = args$align[[i]], by = args$by[[i]], functions = functions ) } }) test_that("we don't segfault when window size > vector size on ops with fill", { x <- c(1:5) w <- 10 gctorture(TRUE) result <- roll_meanr(x, w) gctorture(FALSE) expect_identical( roll_meanr(x, w), rep(NA_real_, length(x)) ) }) test_that("we handle an empty fill properly", { if (!requireNamespace("zoo", quietly = TRUE)) skip("zoo not installed") for (i in 10:100) { data <- 1:i lhs <- zoo::rollapply(data, 3, mean, by = 3) rhs <- roll_mean(data, 3, by = 3, fill = numeric()) expect_identical(lhs, rhs) } }) test_that("median handles NAs appropriately", { y <- c(NA, 1:3, NA) expect_equal( roll_median(y, n = 3L, na.rm = TRUE), c(1.5, 2.0, 2.5) ) })