--- title: "Causal inference with MORIE" output: rmarkdown::html_vignette: toc: true vignette: > %\VignetteIndexEntry{Causal inference with MORIE} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", eval = requireNamespace("morie", quietly = TRUE) ) ``` # Overview This vignette walks through the causal-inference surface of MORIE: ATE, ATT, ATC, augmented IPW (doubly robust), per-unit CATE, group GATE, and sensitivity analysis (the E-value). Each estimator follows the same calling convention --- `data`, `treatment`, `outcome`, `covariates` --- so swapping among them is a matter of changing one function name. # A reproducible synthetic example ```{r setup} library(morie) set.seed(2026) n <- 800 X1 <- rnorm(n) X2 <- rnorm(n) # Confounded treatment assignment ps <- plogis(0.5 * X1 - 0.3 * X2) treat <- as.integer(ps > runif(n)) # True ATE = +1.0 y <- 1.0 * treat + 0.7 * X1 - 0.2 * X2 + rnorm(n, sd = 0.5) df <- data.frame(y = y, treat = treat, X1 = X1, X2 = X2) ``` # Single-robust ATE / ATT / ATC ```{r ate-att-atc} ate <- morie_estimate_ate(df, treatment = "treat", outcome = "y", covariates = c("X1", "X2")) att <- morie_estimate_att(df, treatment = "treat", outcome = "y", covariates = c("X1", "X2")) atc <- morie_estimate_atc(df, treatment = "treat", outcome = "y", covariates = c("X1", "X2")) ate$estimate att$estimate atc$estimate ``` The three quantities estimate slightly different things: - **ATE** (average treatment effect): averaged over the full population. - **ATT** (treated): averaged over the treated subgroup. - **ATC** (controls): averaged over the untreated subgroup. Under no effect heterogeneity in the covariates, all three converge. Under heterogeneity, they diverge in informative ways. # Doubly robust: augmented IPW `morie_estimate_aipw()` is the augmented inverse-probability-weighting estimator. It is consistent if either the propensity model or the outcome model is correctly specified --- the doubly-robust guarantee. ```{r aipw} aipw <- morie_estimate_aipw(df, treatment = "treat", outcome = "y", covariates = c("X1", "X2")) aipw$estimate aipw$se ``` # Per-unit CATE (T-learner / S-learner) ```{r cate} cate <- morie_estimate_cate(df, treatment = "treat", outcome = "y", covariates = c("X1", "X2"), meta_learner = "t_learner") head(cate) ``` Each row of the returned data frame contains a per-unit conditional average treatment effect. # Group-level GATE ```{r gate} df$g <- sample(c("A", "B", "C"), nrow(df), replace = TRUE) gate <- morie_estimate_gate(df, treatment = "treat", outcome = "y", covariates = c("X1", "X2"), group_col = "g") gate ``` The result is one row per group level with `ate`, `se`, and CI. # Sensitivity analysis: the E-value ```{r evalue, eval = exists("morie_e_value")} # Suppose the observed risk ratio is 2.0; how large would an # unmeasured confounder need to be to explain it away? evalue <- morie_e_value(rr = 2.0) evalue ``` The E-value is the minimum strength (on the risk-ratio scale) that an unmeasured confounder would need on both treatment and outcome to fully explain the observed effect. # Where to go next - The companion `mrm-otis-walkthrough` vignette applies the full ten-estimator MRM ensemble to OTIS provincial data. - For survey-weighted versions of these estimators, see the `survey-weighted` vignette.