Getting started
Install the package (URL until General registration completes), load CausalMediation together with CausalTargeted (Super Learner profiles) and optionally CausalDynamics (identification), then estimate TE / NDE / NIE on a δ-grid.
Identify, then estimate
Prefer a typed certificate when you have a DAG:
- Build a graph and call
identify(..., MediationQuery(...))in CausalDynamics. - Convert with
spec_from_identificationor merge viaplan_mediation. - Call
run_mediation(orrun_mediation_gridfor a bareDataFrameAPI).
using CausalMediation, CausalTargeted, CausalDynamics, Graphs, StableRNGs
g = DiGraph(4)
add_edge!(g, 1, 2); add_edge!(g, 1, 3); add_edge!(g, 1, 4)
add_edge!(g, 2, 3); add_edge!(g, 2, 4); add_edge!(g, 3, 4)
names = Dict(1 => :W, 2 => :A, 3 => :M, 4 => :Y)
id = identify(
g, MediationQuery(:A, :Y, [:M]; effect_kind = :interventional);
node_names = names,
)
spec = spec_from_identification(id)
spec.mediators, spec.covariates, spec.moc([:M], [:W], Symbol[])df, _truth = simulate_continuous_mtp_mediation(200; rng = StableRNG(7))
res = run_mediation(
spec, df;
deltas = [0.5],
folds = 2,
n_mc = 16,
estimator = :onestep,
learners = DEFAULT_SL_LEARNERS,
parallel = false,
rng = StableRNG(8),
)
decompose(res)(te = 0.2958679286261231, nde = 0.10323957467960759, nie = 0.19262835394651542)Without a graph, construct MediationSpec by hand (same estimation path):
spec = MediationSpec(:A, :Y; mediators = [:M], covariates = [:W])Intermediate confounding (moc)
When a post-treatment confounder of the mediator–outcome relation sits on the graph, natural effects are not admissible. Pass moc and keep an interventional (or recanting-twin / organic) effect:
using CausalMediation, CausalTargeted, StableRNGs
df, _ = simulate_intermediate_confounding_mediation(200; rng = StableRNG(3))
spec = MediationSpec(
:A, :Y;
mediators = [:M],
covariates = [:W],
moc = [:L],
effect = InterventionalMediation(),
)
res = run_mediation(
spec, df;
deltas = [0.5],
folds = 2,
n_mc = 12,
parallel = false,
rng = StableRNG(4),
)
assumptions(spec)(effect = InterventionalMediation, moc = [:L], natural_admissible = false, requires_moc = true, mediators = [:M], treatment = :A, outcome = :Y)assert_natural_admissible! throws if you request NaturalMediation with nonempty moc (the same gate as CausalDynamics identify).
Estimators and nested Monte Carlo
estimator | Role |
|---|---|
:plugin | Nested-MC plug-in contrasts |
:onestep | Plugin plus EIF correction (default) |
:tmle | Targeting step on the same nuisances |
n_mc controls nested mediator draws. At small n, sweep it:
sweep = mediation_n_mc_sweep(
df, :A, :Y;
covar = [:W],
mediators = [:M],
n_mc_values = [8, 16, 32],
delta = 0.5,
folds = 2,
)
mediation_stability_markdown(sweep)Effect families
| Construct | Typical use |
|---|---|
InterventionalMediation() | Default RI / randomised intermediate under moc |
NaturalMediation() | Classical NDE/NIE when moc is empty |
OrganicMediation() | Lok organic effects |
RecantingTwinMediation() | Path-specific / RT contrasts |
ControlledDirect(m = …) | Fix mediators at specified levels |
Soft façades in CausalTargeted
Older CT names (run_crumble_*, engine :crumble) soft-deprecate to this package’s APIs. Prefer using CausalMediation and run_mediation in new code.