Skip to content

Commit 25dcd5f

Browse files
committed
Merge branch 'frosting' of https://github.com/cmu-delphi/epipredict into km-kill-lags-good
2 parents e978089 + 8b0c186 commit 25dcd5f

9 files changed

+180
-5
lines changed

NAMESPACE

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export(smooth_arx_args_list)
6767
export(smooth_arx_forecaster)
6868
export(step_epi_ahead)
6969
export(step_epi_lag)
70+
export(step_epi_naomit)
7071
export(validate_layer)
7172
import(recipes)
7273
importFrom(generics,augment)

R/epi_workflow.R

+3-5
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,13 @@
3636
#' wf <- epi_workflow(r, linear_reg())
3737
#'
3838
#' wf
39-
epi_workflow <- function(preprocessor = NULL, spec = NULL,
40-
postprocessor = NULL) {
39+
epi_workflow <- function(preprocessor = NULL, spec = NULL, postprocessor = NULL) {
4140
out <- workflows::workflow(spec = spec)
4241
class(out) <- c("epi_workflow", class(out))
4342

4443
if (is_epi_recipe(preprocessor)) {
45-
return(add_epi_recipe(out, preprocessor))
46-
}
47-
if (!is_null(preprocessor)) {
44+
out <- add_epi_recipe(out, preprocessor)
45+
}else if (!is_null(preprocessor)) {
4846
out <- workflows:::add_preprocessor(out, preprocessor)
4947
}
5048
if (!is_null(postprocessor)) {

R/step_epi_naomit.R

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#' Unified NA omission wrapper function for recipes
2+
#'
3+
#' @param recipe Recipe to be used for omission steps
4+
#'
5+
#' @return Omits NA's from both predictors and outcomes at training time
6+
#' to fit the model. Also only omits associated predictors and not
7+
#' outcomes at prediction time due to lack of response and avoidance
8+
#' of data loss.
9+
#' @export
10+
#' @examples
11+
#' case_death_rate_subset %>%
12+
#' epi_recipe() %>%
13+
#' step_epi_naomit()
14+
15+
step_epi_naomit <- function(recipe) {
16+
stopifnot(inherits(recipe, "recipe"))
17+
recipe %>%
18+
recipes::step_naomit(all_predictors()) %>%
19+
recipes::step_naomit(all_outcomes(), skip = TRUE)
20+
}

man/step_epi_naomit.Rd

+25
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-assign_arg_list.R

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
test_that("First argument must be a list",{
2+
expect_error(assign_arg_list(c(1,2,3)))
3+
})
4+
test_that("All arguments should be named",{
5+
expect_error(assign_arg_list(list(1,2)))
6+
})
7+
test_that("assign_arg_list works as intended",{
8+
assign_arg_list(list(a="dog",b=2))
9+
expect_identical(a,"dog")
10+
expect_identical(b,2)
11+
})

tests/testthat/test-df_mat_mul.R

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
df <- data.frame(matrix(1:100, ncol = 5))
2+
mat <- matrix(1:4, ncol = 2)
3+
4+
test_that("First input must be a data frame and second
5+
input must be a matrix", {
6+
expect_error(df_mat_mul(df,20))
7+
expect_error(df_mat_mul(30,mat))
8+
})
9+
10+
test_that("Argument name is a character", {
11+
expect_error(df_mat_mul(df, mat, 100))
12+
})
13+
14+
test_that("The length of names does not differ from the length of the number
15+
of outputs" ,{
16+
expect_error(df_mat_mul(df, mat, c("a","b","c"), 2:3))
17+
})
18+
19+
test_that("The number of columns of the first data frame cannot differ from the
20+
number of rows of the second matrix, hence preventing incompatible
21+
matrix multiplication", {
22+
expect_error(df_mat_mul(df, mat, "z", 1:3))
23+
})
24+
25+
X <- df[c(1,4,5)]
26+
Z <- as.data.frame(as.matrix(df[2:3]) %*% mat)
27+
colnames(Z) <- c("z1","z2")
28+
output <- cbind(X,Z)
29+
30+
test_that("Names are being handled properly", {
31+
expect_identical(df_mat_mul(df, mat, "z", 2:3),output)
32+
expect_identical(df_mat_mul(df, mat, c("z1","z2"), 2:3),output)
33+
})
34+
35+
test_that("Other tidyselect functionalities are working", {
36+
mult <- df_mat_mul(df, mat, "z", dplyr::num_range("X", 2:3))
37+
expect_identical(mult,output)
38+
expect_identical(df_mat_mul(df, mat, "z", 2, 3),output)
39+
# Mismatched names should not work:
40+
expect_error(df_mat_mul(df, mat, "z", dplyr::num_range("Y", 2:3)))
41+
})

tests/testthat/test-epi_workflow.R

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
test_that("postprocesser was evaluated", {
3+
r <- epi_recipe(case_death_rate_subset)
4+
s <- parsnip::linear_reg()
5+
f <- frosting()
6+
7+
ef <- epi_workflow(r, s, f)
8+
ef2 <- epi_workflow(r, s) %>% add_frosting(f)
9+
10+
expect_true(epipredict:::has_postprocessor(ef))
11+
expect_true(epipredict:::has_postprocessor(ef2))
12+
})
13+
14+
15+
test_that("outcome of the two methods are the same", {
16+
jhu <- case_death_rate_subset
17+
18+
r <- epi_recipe(jhu) %>%
19+
step_epi_lag(death_rate, lag = c(0, 7)) %>%
20+
step_epi_ahead(death_rate, ahead = 7) %>%
21+
step_epi_lag(case_rate, lag = c(7)) %>%
22+
step_naomit(all_predictors()) %>%
23+
step_naomit(all_outcomes())
24+
25+
s <- parsnip::linear_reg()
26+
f <- frosting() %>%
27+
layer_predict() %>%
28+
layer_naomit(.pred) %>%
29+
layer_residual_quantile()
30+
31+
ef <- epi_workflow(r, s, f)
32+
ef2 <- epi_workflow(r, s) %>% add_frosting(f)
33+
34+
expect_equal(ef,ef2)
35+
})

tests/testthat/test-grab_names.R

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
df <- data.frame(b=1,c=2,ca=3,cat=4)
2+
3+
test_that("Names are grabbed properly", {
4+
expect_identical(grab_names(df,dplyr::starts_with("ca")),
5+
subset(names(df),startsWith(names(df), "ca"))
6+
)
7+
})

tests/testthat/test-step_epi_naomit.R

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
library(dplyr)
2+
library(parsnip)
3+
library(workflows)
4+
5+
# Random generated dataset
6+
x <- tibble(geo_value = rep("nowhere",200),
7+
time_value = as.Date("2021-01-01") + 0:199,
8+
case_rate = 1:200,
9+
death_rate = 1:200) %>%
10+
epiprocess::as_epi_df()
11+
12+
# Preparing the datasets to be used for comparison
13+
r <- epi_recipe(x) %>%
14+
step_epi_ahead(death_rate, ahead = 7) %>%
15+
step_epi_lag(death_rate, lag = c(0,7,14))
16+
17+
test_that("Argument must be a recipe", {
18+
expect_error(step_epi_naomit(x))
19+
})
20+
21+
z1 <- step_epi_naomit(r)
22+
z2 <- r %>%
23+
step_naomit(all_predictors()) %>%
24+
step_naomit(all_outcomes(), skip = TRUE)
25+
26+
# Checks the behaviour of a step function, omitting the quosure and id that
27+
# differ from one another, even with identical behaviour
28+
behav <- function(recipe,step_num) recipe$steps[[step_num]][-1][-5]
29+
# Checks the class type of an object
30+
step_class <- function(recipe,step_num) class(recipe$steps[step_num])
31+
32+
test_that("Check that both functions behave the same way", {
33+
expect_identical(behav(z1,3),behav(z2,3))
34+
expect_identical(behav(z1,4),behav(z2,4))
35+
expect_identical(step_class(z1,3),step_class(z2,3))
36+
expect_identical(step_class(z1,4),step_class(z2,4))
37+
})

0 commit comments

Comments
 (0)