Skip to content

Commit 5a42234

Browse files
authored
Merge pull request #150 from cmu-delphi/lint-and-typos
Lint and typos
2 parents 8ee8fdf + fed4a91 commit 5a42234

12 files changed

+478
-292
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,4 @@ Config/testthat/edition: 3
6767
Encoding: UTF-8
6868
LazyData: true
6969
Roxygen: list(markdown = TRUE)
70-
RoxygenNote: 7.2.2
70+
RoxygenNote: 7.2.3

R/arx_forecaster.R

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ arx_forecaster <- function(epi_data,
3838

3939
# --- validation
4040
validate_forecaster_inputs(epi_data, outcome, predictors)
41+
if (!inherits(args_list, "arx_alist")) {
42+
cli_stop("args_list was not created using `arx_args_list().")
43+
}
4144
if (!is.list(trainer) || trainer$mode != "regression")
4245
cli_stop("{trainer} must be a `parsnip` method of mode 'regression'.")
4346
lags <- arx_lags_validator(predictors, args_list$lags)
@@ -121,7 +124,7 @@ arx_lags_validator <- function(predictors, lags) {
121124
#' [layer_residual_quantiles()] for more information. The default,
122125
#' `character(0)` performs no grouping.
123126
#'
124-
#' @return A list containing updated parameter choices.
127+
#' @return A list containing updated parameter choices with class `arx_alist`.
125128
#' @export
126129
#'
127130
#' @examples
@@ -151,14 +154,15 @@ arx_args_list <- function(lags = c(0L, 7L, 14L),
151154
arg_is_probabilities(levels, allow_null = TRUE)
152155

153156
max_lags <- max(lags)
154-
enlist(lags = .lags,
155-
ahead,
156-
min_train_window,
157-
levels,
158-
forecast_date,
159-
target_date,
160-
symmetrize,
161-
nonneg,
162-
max_lags,
163-
quantile_by_key)
157+
structure(enlist(lags = .lags,
158+
ahead,
159+
min_train_window,
160+
levels,
161+
forecast_date,
162+
target_date,
163+
symmetrize,
164+
nonneg,
165+
max_lags,
166+
quantile_by_key),
167+
class = "arx_alist")
164168
}

R/flatline_forecaster.R

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ flatline_forecaster <- function(epi_data,
3232
args_list = flatline_args_list()) {
3333

3434
validate_forecaster_inputs(epi_data, outcome, "time_value")
35+
if (!inherits(args_list, "flatline_alist")) {
36+
cli_stop("args_list was not created using `flatline_args_list().")
37+
}
3538
keys <- epi_keys(epi_data)
3639
ek <- keys[-1]
3740
outcome <- rlang::sym(outcome)
@@ -75,7 +78,7 @@ flatline_forecaster <- function(epi_data,
7578
#'
7679
#' @inheritParams arx_args_list
7780
#'
78-
#' @return A list containing updated parameter choices.
81+
#' @return A list containing updated parameter choices with class `flatline_alist`.
7982
#' @export
8083
#'
8184
#' @examples
@@ -99,14 +102,15 @@ flatline_args_list <- function(ahead = 7L,
99102
arg_is_lgl(symmetrize, nonneg)
100103
arg_is_probabilities(levels, allow_null = TRUE)
101104

102-
enlist(ahead,
103-
min_train_window,
104-
forecast_date,
105-
target_date,
106-
levels,
107-
symmetrize,
108-
nonneg,
109-
quantile_by_key)
105+
structure(enlist(ahead,
106+
min_train_window,
107+
forecast_date,
108+
target_date,
109+
levels,
110+
symmetrize,
111+
nonneg,
112+
quantile_by_key),
113+
class = "flatline_alist")
110114
}
111115

112116
validate_forecaster_inputs <- function(epi_data, outcome, predictors) {

README.Rmd

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ knitr::opts_chunk$set(
1919
[![R-CMD-check](https://github.com/cmu-delphi/epipredict/workflows/R-CMD-check/badge.svg)](https://github.com/cmu-delphi/epipredict/actions)
2020
<!-- badges: end -->
2121

22-
**Note:** This package is currently in development and likely will not work as expected.
22+
**Note:** This package is currently in development and may not work as expected. Please file bug reports as issues in this repo, and we will do our best to address them quickly.
2323

2424
## Installation
2525

2626
You can install the development version of epipredict from [GitHub](https://github.com/) with:
2727

2828
``` r
29-
# install.packages("devtools")
30-
devtools::install_github("cmu-delphi/epipredict")
29+
# install.packages("remotes")
30+
remotes::install_github("cmu-delphi/epipredict")
3131
```
3232

3333
## Documentation
@@ -39,7 +39,7 @@ You can view documentation for the `main` branch at <https://cmu-delphi.github.i
3939

4040
**We hope to provide:**
4141

42-
1. A set of basic, easy-to-use forecasters that work out of the box. You should be able to do a reasonably limited amount of customization on them. (Any serious customization happens with point number 2.) For the basic forecasters, we should provide, at least:
42+
1. A set of basic, easy-to-use forecasters that work out of the box. You should be able to do a reasonably limited amount of customization on them. For the basic forecasters, we currently provide:
4343
* Baseline flat-line forecaster
4444
* Autoregressive forecaster
4545
* Autoregressive classifier
@@ -49,15 +49,58 @@ You can view documentation for the `main` branch at <https://cmu-delphi.github.i
4949
* Predictor: make predictions, using a fitted model object
5050
* Postprocessor: do things to the predictions before returning
5151

52-
**Target audience:**
52+
**Target audiences:**
5353

5454
* Basic. Has data, calls forecaster with default arguments.
5555
* Intermediate. Wants to examine changes to the arguments, take advantage of built in flexibility.
5656
* Advanced. Wants to write their own forecasters. Maybe willing to build up from some components that we write.
5757

58-
The Advanced user should find their task to be relatively easy (and we'll show them how).
58+
The Advanced user should find their task to be relatively easy. Examples of these tasks are illustrated in the [vignettes and articles](https://cmu-delphi.github.io/epipredict).
59+
60+
## Intermediate example
61+
62+
The package comes with some built-in historical data for illustration, but
63+
up-to-date versions of this could be downloaded with the [`{covidcast}` package](https://cmu-delphi.github.io/covidcast/covidcastR/index.html) and processed using [`{epiprocess}`](https://cmu-delphi.github.io/epiprocess/).[^1]
64+
65+
[^1]: Other epidemiological signals for non-Covid related illnesses are available with [`{epidatr}`](https://github.com/cmu-delphi/epidatr) which interfaces directly to Delphi's [Epidata API](https://cmu-delphi.github.io/delphi-epidata/)
66+
67+
```{r epidf, message=FALSE}
68+
library(tidyverse)
69+
library(epipredict)
70+
jhu <- case_death_rate_subset
71+
jhu
72+
```
73+
74+
To create and train a simple auto-regressive forecaster to predict the death rate two weeks into the future using past (lagged) deaths and cases, we could use the following function.
75+
76+
```{r make-forecasts, warning=FALSE}
77+
two_week_ahead <- arx_forecaster(
78+
jhu,
79+
outcome = "death_rate",
80+
predictors = c("case_rate", "death_rate"),
81+
args_list = arx_args_list(
82+
lags = list(c(0,1,2,3,7,14), c(0,7,14)),
83+
ahead = 14
84+
)
85+
)
86+
```
87+
88+
In this case, we have used a number of different lags for the case rate, while only using 3 weekly lags for the death rate (as predictors). The result is both a fitted model object which could be used any time in the future to create different forecasts, as well as a set of predicted values (and prediction intervals) for each location 14 days after the last available time value in the data.
89+
90+
```{r print-model}
91+
two_week_ahead$epi_workflow
92+
```
93+
94+
The fitted model here involved preprocessing the data to appropriately generate lagged predictors, estimating a linear model with `stats::lm()` and then postprocessing the results to be meaningful for epidemiological tasks. We can also examine the predictions.
95+
96+
```{r show-preds}
97+
two_week_ahead$predictions
98+
```
99+
100+
The results above show a distributional forecast produced using data through the end of 2021 for the 14th of January 2022. A prediction for the death rate per 100K inhabitants is available for every state (`geo_value`) along with a 90% predictive interval.
101+
102+
<!--
59103
60-
**Example:**
61104
During a quiet period, a user decides they want to first predict whether a surge is about to occur, say using variant information from GISAID. Then for surging locations, they want to train an AR model using past surges in the same location. Everywhere else, they predict a flat line. We should be able to do this in a few lines of code.
62105
63106
Delphi's own forecasts have been produced/evaluated in this way for a while now, but the code base is scattered and evolving. We want to consolidate, generalize, and simplify to allow others to benefit as well.
@@ -84,25 +127,11 @@ my_fcaster(lead(cases, 7) ~ ., epi_df, key_vars, time_vars)
84127
85128
The hypothetical example of first classifying, then fitting different models would also fit into this framework. And this isn't far from our current production models.
86129
87-
### Why doesn't this exist
88130
89-
Closest neighbor is [`{fable}`](https://fable.tidyverts.org/). It does some of what we want but has a few major downsides:
90131
91-
1. Small set of standard Time Series models.
92-
* Small modifications are hard (e.g. can't "just use" `glmnet` instead of `lm`) in an AR model.
93-
1. Multi-period forecasting is model-based only.
94-
* This is "iterative" forecasting, and is very bad in epidemiology.
95-
* Much better with simple models to use "direct" forecasting.
96-
1. Confidence bands are model-based only.
97-
* In epi tasks, these dramatically under-cover.
98-
1. Layering is not possible/natural
99-
1. Can't use methods that aren't already implemented.
100-
101-
The forecasts we did above can't be produced with `{fable}`.
102-
103-
104-
**However:** The developers behind `{fable}` wrote a package called `{fabletools}` that powers model creation (based on `R6`). We can almost certainly borrow some of that technology to lever up.
105132
106133
### What this isn't
107134
108135
This is not a framework for SIR models. We intend to create some simple versions, but advanced models---those that use variants, hospitalizations, different types of immunity, age stratification, etc.---cannot be compartmentalized in the same way (though see [pypm](https://pypm.github.io/home/)). These types of models also are better at scenario modeling than short term forecasts unless they are quite complicated.
136+
137+
-->

0 commit comments

Comments
 (0)