Skip to contents

Fits a segmented quasi-Poisson regression to estimate the immediate and sustained effects of one or more interruptions (policies, extreme events, pandemics) on a daily health outcome count series. The model decomposes each interruption into a level change (immediate step) and a slope change (sustained trend shift), controlling for the underlying time trend and seasonal variation via harmonic terms. A counterfactual projection shows what would have been expected had the interruption not occurred.

Usage

sus_mod_its(
  data,
  outcome_col = "n_obitos",
  date_col = "date",
  interruption_dates,
  harmonics = 2L,
  family = "quasipoisson",
  covariates = NULL,
  alpha = 0.05,
  counterfactual = TRUE,
  lang = "pt",
  verbose = TRUE
)

Arguments

data

A climasus_df at stage "aggregate" or "climate", or any data.frame with a date column and an integer count column.

outcome_col

Character. Name of the daily health outcome count column. Default: "n_obitos".

date_col

Character. Name of the date column. Default: "date".

interruption_dates

Date or character vector of at least one interruption date (ISO "YYYY-MM-DD" format). Must lie strictly within the data range. For a single interruption pass a scalar; for multiple, pass a vector.

harmonics

Integer. Number of sinusoidal harmonic pairs for seasonal control (\(H\) in the model above). 0 suppresses seasonal terms. Default: 2L.

family

Character. GLM family: "quasipoisson" (default, robust to overdispersion) or "poisson".

covariates

Character vector or NULL. Names of additional columns to include as linear confounders (e.g., "rh_pct", "holiday"). Must be numeric or dummy-coded. Default: NULL.

alpha

Numeric. Significance level for confidence intervals. Default: 0.05 (95% CI).

counterfactual

Logical. Compute and return counterfactual predictions. Default: TRUE.

lang

Character. Language for messages: "pt" (default), "en", "es".

verbose

Logical. Print progress messages. Default TRUE.

Value

A climasus_its list with:

$model

The fitted glm object.

$effects

Tibble with one row per interruption: label, interruption_date, level_ratio, level_ci_lo, level_ci_hi, level_p, slope_daily_log, slope_ratio_annual, slope_p.

$counterfactual

Tibble with daily date, observed, predicted (fitted values), counterfactual, cf_lo, cf_hi, ratio_to_cf, prevented. NULL when counterfactual = FALSE.

$segments

Tibble with one row per segment (pre-interruption and each post-interruption interval): segment, start_date, end_date, n_days, mean_observed, mean_predicted, mean_counterfactual.

$data

The analysis dataset with all model covariates.

$meta

Analysis parameters and diagnostics.

Statistical framework

For \(K\) interruption dates \(T_1 < T_2 < \ldots < T_K\), the segmented Poisson GLM is:

$$\log(E[Y_t]) = \beta_0 + \beta_1 t + \sum_{j=1}^{K}\left[\beta_{2j}\, D_j(t) + \beta_{2j+1}\, S_j(t)\right] + \sum_{k=1}^{H}\left[\gamma_k \sin\!\left(\tfrac{2\pi k\, t}{365.25}\right) + \delta_k \cos\!\left(\tfrac{2\pi k\, t}{365.25}\right)\right] + \mathbf{z}_t^\top \boldsymbol{\eta}$$

where \(D_j(t) = \mathbf{1}(t \ge T_j)\) is the step indicator and \(S_j(t) = \max(0,\, t - T_j)\) is the slope-change ("hockey stick") basis. The immediate rate ratio at interruption \(j\) is \(RR_j = e^{\beta_{2j}}\); the sustained trend shift is \(e^{\beta_{2j+1}}\) per day (or \(e^{365.25\,\beta_{2j+1}}\) per year).

Counterfactual

The counterfactual is the model prediction with all \(D_j\) and \(S_j\) set to zero — i.e., the pre-interruption baseline trend projected forward through the study period. The difference observed - counterfactual is the estimated total attributable change.

References

Bernal, J.L., Cummins, S., & Gasparrini, A. (2017). Interrupted time series regression for the evaluation of public health interventions: a tutorial. International Journal of Epidemiology, 46(1), 348-355. doi:10.1093/ije/dyw098

Penfold, R.B., & Zhang, F. (2013). Use of interrupted time series analysis in evaluating health care quality improvements. Academic Pediatrics, 13(6 Suppl), S38-44. doi:10.1016/j.acap.2013.08.002

Examples

if (FALSE) { # \dontrun{
# Single interruption (COVID-19 pandemic onset)
its <- sus_mod_its(
  df_daily,
  outcome_col       = "n_obitos",
  interruption_dates = "2020-03-17",
  harmonics         = 2L,
  lang              = "pt"
)
print(its)
tidy(its)

# Multiple interruptions
its2 <- sus_mod_its(
  df_daily,
  outcome_col        = "n_obitos",
  interruption_dates = c("2020-03-17", "2021-01-18"),
  lang               = "en"
)
} # }