library("causatr")
data("nhefs", package = "causatr")
fit <- causat(nhefs, outcome = "wt82_71", treatment = "qsmk",
confounders = ~ sex + age + wt71)
# ATE: mean difference with sandwich SE
result <- contrast(fit,
interventions = list(quit = static(1), continue = static(0)),
type = "difference"
)
# ATT: override estimand in contrast() (gcomp only)
result_att <- contrast(fit,
interventions = list(quit = static(1), continue = static(0)),
estimand = "ATT"
)
# Subgroup effect: age > 50
result_sub <- contrast(fit,
interventions = list(quit = static(1), continue = static(0)),
subset = quote(age > 50)
)
# Continuous treatment: shift with NULL reference
fit_cont <- causat(nhefs, outcome = "wt82_71",
treatment = "smokeintensity",
confounders = ~ sex + age + wt71)
contrast(fit_cont,
interventions = list(reduce10 = shift(-10), observed = NULL),
type = "difference"
)
# Categorical treatment: three arms, reference = "radio"
contrast(fit_cat,
interventions = list(chemo = static("A"), radio = static("B"),
combo = static("C")),
type = "difference",
reference = "radio"
)Compute causal contrasts from a fitted model
Description
Standardises outcome model predictions under each named intervention and reports pairwise causal contrasts (differences, ratios, or odds ratios) with uncertainty estimates.
For all three causal estimators, contrast() computes E[Y^a] by setting each individual’s treatment to the intervened value and averaging the fitted outcome model predictions over the target population. The target population is controlled by estimand (or subset for subgroup effects). The estimators differ only in how the outcome model was fitted; variance is computed by the unified influence-function engine variance_if() (R/variance_if.R), which handles all four cases (g-comp, IPW, matching, ICE) via one entry point. See vignettes/variance-theory.qmd for the derivation and the R/variance_if.R roxygen header for the architecture.
-
“gcomp”: standardglm/gamon the full data; one-model IF correction viaprepare_model_if()+apply_model_correction(). -
“ipw”: density-ratio weighted MSM refit per intervention; IF Channel 2 is the stacked-sandwich MSM-plus-propensity correction assembled bycompute_ipw_if_self_contained_one(), with the cross-derivative \(A_{\beta\alpha}\) computed numerically bynumDeriv::jacobian(). -
“matching”:glm()on the matched sample with match weights; IF is computed on the matched sample and aggregated cluster-robustly onmatched$subclassviavcov_from_if(cluster = …).
Usage
contrast(
fit,
interventions,
type = c("difference", "ratio", "or"),
estimand = NULL,
subset = NULL,
reference = NULL,
ci_method = c("sandwich", "bootstrap"),
n_boot = 500L,
conf_level = 0.95,
by = NULL,
parallel = getOption("boot.parallel", "no"),
ncpus = getOption("boot.ncpus", 1L)
)
Arguments
fit
|
A causatr_fit object returned by causat().
|
interventions
|
A named list of interventions. Each element must be one of:
Note: Non-static interventions ( contrast() on a causatr_fit returned by causat_survival() aborts with an informative error. The pooled logistic fit itself works.
|
type
|
Character. The contrast scale: “difference” (default), “ratio”, or “or” (odds ratio). All pairwise contrasts are reported.
|
estimand
|
Character or NULL. The target estimand: “ATE”, “ATT”, or “ATC”. For estimator = “gcomp”, overrides the estimand stored in fit (allowing one fit to produce multiple estimands). For estimator = “ipw” or “matching”, must match the estimand used at fitting time – changing it aborts with an informative message. If NULL, defaults to fit$estimand. Mutually exclusive with subset.
|
subset
|
A quoted expression (quote(…)) defining a subgroup to average over instead of an estimand. Evaluated in the context of the fitted data. Works for any treatment type. For example, subset = quote(age > 50) or subset = quote(A == 1) (the latter is equivalent to estimand = “ATT” for binary treatments). Mutually exclusive with estimand.
|
reference
|
Character or NULL. Name of the reference intervention (the denominator/subtracted value for pairwise contrasts). Default: the first intervention in the list. Only relevant when type = “difference” or “ratio” and there are more than two interventions. For categorical treatments, use this to specify the reference level.
|
ci_method
|
Character. The variance/CI approach: “sandwich” (default) or “bootstrap”.
|
n_boot
|
Integer. Number of bootstrap replications when ci_method = “bootstrap”. Default 500.
|
conf_level
|
Numeric. Confidence level for intervals. Default 0.95.
|
by
|
Character or NULL. Name of a variable to stratify estimates by (effect modification). If provided, E[Y^a] is computed within each level of by.
|
parallel
|
Character. Parallelisation backend for bootstrap (ci_method = “bootstrap” only). “no” (default) runs sequentially; “multicore” uses forked processes via parallel::mclapply() (Unix only); “snow” uses socket clusters via parallel::parLapply() (cross-platform). Passed directly to boot::boot(). Ignored when ci_method = “sandwich”.
|
ncpus
|
Integer. Number of CPU cores for parallel bootstrap. Default getOption(“boot.ncpus”, 1L). Passed directly to boot::boot().
|
Details
Estimands and standardisation
For each intervention a, contrast() evaluates the intervention function on the target rows to obtain the intervened treatment vector \(a(L_i)\), then computes:
\(E[Y^a] = (1/|S|) \sum_{i \in S} \hat{E}[Y | A = a(L_i), L_i]\)
where S is the set of rows determined by the estimand:
-
“ATE”: all rows (full population) -
“ATT”: rows whereA == 1(observed treated) -
“ATC”: rows whereA == 0(observed controls) -
subset: rows satisfying the quoted expression
For “gcomp”, one fit supports multiple estimands because the outcome model is the same – only the rows averaged over change. For “ipw” and “matching”, the estimand is baked into the weights/matching and cannot be changed after fitting.
Estimand applicability
| Treatment type | ATE | ATT/ATC | subset |
| Binary point | Yes | Yes | Yes |
| Continuous point | Yes | No (abort) | Yes |
| Categorical point | Yes | No (abort) | Yes |
| Multivariate point | Yes | No (abort) | Yes |
| Longitudinal | Yes | No (abort) | Yes |
Treatment types and intervention support
| Method | Treatment types | Intervention types |
“gcomp”
|
binary, categorical, continuous, multivariate | all |
“ipw”
|
binary, continuous |
binary: static() / dynamic() / ipsi(); continuous: shift() / scale_by()
|
“matching”
|
binary |
static() only
|
Variance estimation
-
“sandwich”: The unified influence-function enginevariance_if(). Per-individual IF = Channel 1 (direct covariate-sampling term) + Channel 2 (one correction per nuisance model). Aggregated viavcov_from_if(), with cluster-robust aggregation for matching. Mathematically equivalent to the stacked M-estimation sandwich; seevignettes/variance-theory.qmdSections 3-4. -
“bootstrap”: Resamples individuals (entire pipeline refittedn_boottimes). Respects cluster structure for longitudinal data. -
The delta method is applied internally for ratio / odds-ratio contrasts on top of the
“sandwich”vcov; it is not a separateci_methodoption.
Value
A causatr_result object with slots:
-
estimates -
data.table with one row per intervention:
intervention,estimate,se,ci_lower,ci_upper. -
contrasts -
data.table with one row per pairwise comparison:
comparison,estimate,se,ci_lower,ci_upper. -
type - Contrast scale.
-
estimand -
“ATE”,“ATT”,“ATC”, or“subset”. -
ci_method - Inference approach.
-
reference - Name of the reference intervention.
-
interventions - The intervention list.
-
n - Number of individuals averaged over.
-
estimator - Causal estimator from the fit.
-
vcov - Full variance-covariance matrix for all E[Y^a].
-
call - The original call.
References
Hernan MA, Robins JM (2025). Causal Inference: What If. Chapman & Hall/CRC. Chapters 12-13.
Imai K, King G, Stuart EA (2011). Misunderstandings between experimentalists and observationalists about causal inference. Journal of the Royal Statistical Society Series A 171:481-502.
Zivich PN, Ross RK, Shook-Sa BE, Cole SR, Edwards JK (2024). Empirical sandwich variance estimator for iterated conditional expectation g-computation. Statistics in Medicine 43:5562-5572.
See Also
causat(), static(), shift(), dynamic(), coef.causatr_result(), confint.causatr_result()