
Time-Stratified Case-Crossover Analysis for Climate-Health Data
Source:R/sus_mod_casecrossover.R
sus_mod_casecrossover.RdFits a time-stratified case-crossover model to quantify the association
between a climate exposure and a daily health outcome. Each time stratum
(month or week) acts as its own control, removing long-term trends and
seasonal confounding by design. Two fitting methods are supported:
"conditional_poisson" (GLM with stratum fixed effects, default) for
aggregate count data, and "clogit" (conditional logistic regression) for
binary outcomes or rare events.
Usage
sus_mod_casecrossover(
data,
outcome_col = "n_obitos",
exposure_col,
covariates = NULL,
stratum = "month",
lag = 0L,
method = "conditional_poisson",
family = "quasipoisson",
alpha = 0.05,
lang = "pt",
verbose = TRUE
)Arguments
- data
A
climasus_dfat stage"aggregate"or"climate"(produced bysus_climate_aggregate()), or anydata.framecontaining at minimum adatecolumn (Date), an outcome count column, and an exposure column.- outcome_col
Character. Name of the daily health outcome count column (e.g.,
"n_obitos","n_internacoes"). Default:"n_obitos".- exposure_col
Character. Name of the exposure column. Required; no auto-detection is performed (unlike
sus_mod_dlnm()). Examples:"tair_dry_bulb_c","pm25_mean","precip_mm".- covariates
Character vector or
NULL. Names of additional columns to include as linear confounders. These should be time-varying within strata (e.g., day-of-week dummy, holiday indicator, relative humidity). Long-term trends are already controlled by the strata. Default:NULL.- stratum
Character. Time stratum type or name of an existing column:
"month"(default): year-month strata (e.g.,"2021-07")."week": ISO year-week strata (e.g.,"2021-W27").Any column name in
data: uses that column's values as stratum IDs.
- lag
Integer or integer vector. Lag(s) to apply to the exposure before fitting. A single integer uses that specific lag; a vector uses the mean of exposures at all specified lags. Default:
0L(same-day exposure).- method
Character. Fitting method:
"conditional_poisson"(default): GLM with stratum fixed effects. Preferred for aggregate count data; usesstats::glm()with the specifiedfamily."clogit": conditional logistic regression viasurvival::clogit(). Requires thesurvivalpackage. Treats outcome as binary (is_case = count > 0); best for rare events.
- family
Character. GLM family for
method = "conditional_poisson":"quasipoisson"(default, robust to overdispersion) or"poisson". Ignored formethod = "clogit".- alpha
Numeric. Significance level for confidence intervals. Default:
0.05(95% CI).- lang
Character. Language for messages:
"pt"(default),"en","es".- verbose
Logical. Print progress messages. Default
TRUE.
Value
A climasus_casecrossover list with:
$modelThe fitted model object: a
glmfor"conditional_poisson"or aclogitobject for"clogit".$or_tableTibble with one row per exposure term:
term,lag_spec,estimate(log-OR),or,or_lo,or_hi,p_value.$dataThe analysis dataset after lag creation and NA removal: columns
date,outcome_val,exposure_val,stratum_id, and any covariates.$diagnosticsList:
n_obs,n_cases,n_strata,disp_ratio(for"conditional_poisson"),method,family.$metaList of analysis parameters:
outcome_col,exposure_col,covariates,stratum,lag,method,family,alpha,call_time.
Statistical framework
"conditional_poisson" method (Whitaker et al., 2006):
$$\log(E[Y_t]) = \alpha_s + \beta X_t + \mathbf{z}_t^\top \boldsymbol{\gamma}$$
where \(\alpha_s\) is a stratum-specific intercept (absorbed as
factor(stratum_id) in the GLM), \(X_t\) is the (possibly lagged or
averaged) exposure on day \(t\), and \(\mathbf{z}_t\) are optional
time-varying covariates. The rate ratio is \(RR = e^\beta\).
"clogit" method (Maclure, 1991; Levy et al., 2001):
Uses survival::clogit() with the binary indicator
\(D_t = \mathbf{1}(Y_t > 0)\) as the outcome. Each case day is matched
to all other days within the same stratum as controls. This method is most
appropriate for rare events (low daily counts) and binary outcomes.
Lag specification
The lag argument controls how the daily exposure is lagged before the
association is estimated:
Single integer (e.g.,
lag = 0): uses the exposure exactlylagdays before the outcome day.Integer vector (e.g.,
lag = 0:6): uses the arithmetic mean of exposures at all specified lags — a moving average common for temperature (e.g.,lag = 0:6is the "lag 0-6" or "mean temperature over 7 days").
References
Maclure, M. (1991). The case-crossover design: a method for studying transient effects on the risk of acute events. American Journal of Epidemiology, 133(2), 144-153. doi:10.1093/oxfordjournals.aje.a115853
Levy, D., Lumley, T., Sheppard, L., Kaufman, J., & Checkoway, H. (2001). Referent selection in case-crossover analyses of acute health effects of air pollution. Epidemiology, 12(2), 186-192.
Whitaker, H.J., Farrington, C.P., Spiessens, B., & Musonda, P. (2006). Tutorial in biostatistics: the self-controlled case series method. Statistics in Medicine, 25(10), 1768-1797. doi:10.1002/sim.2302
Armstrong, B.G., Gasparrini, A., & Tobias, A. (2014). Conditional Poisson models: a flexible alternative to conditional logistic case crossover analysis. BMC Medical Research Methodology, 14, 122. doi:10.1186/1471-2288-14-122
Examples
if (FALSE) { # \dontrun{
# Conditional Poisson with lag-0 temperature
cc <- sus_mod_casecrossover(
df_daily,
outcome_col = "n_obitos",
exposure_col = "tair_dry_bulb_c",
stratum = "month",
lag = 0L,
lang = "pt"
)
print(cc)
tidy(cc)
# Moving-average lag 0-6
cc_lag06 <- sus_mod_casecrossover(
df_daily,
outcome_col = "n_obitos",
exposure_col = "tair_dry_bulb_c",
lag = 0L:6L,
lang = "en"
)
} # }