Reference: Causal Inference Glossary
This is the working vocabulary file for the Blue Harbor Hotels causal-inference series (Maya, Priya, and the 90-day cancellation policy). Treat it as a lookup table: every term that recurs across the 10-part series lives here, with one plain-English definition, a tiny diagram, and a pointer to where it shows up in the corpus.
If you read the series in order, you’ll notice the same five or six ideas get re-explained in each article. They live here so the articles can stay focused on the method (sensitivity analysis, IV estimation, counterfactual reasoning) instead of re-defining “DAG” every time.
Roster
| Term | Plain-English definition | Mini-DAG (ASCII) | Range / type | When to use it | Used in corpus article |
|---|---|---|---|---|---|
Treatment (Z, T, or A) | The variable whose effect we want to measure — the “intervention.” In Blue Harbor, whether a hotel offered the 90-day cancellation policy. | Z ──► Y | binary or continuous | Define it before you look at data; it’s the policy/feature you’d push a button to change. | All 10 causal-inference articles, plus the A/B-testing article |
Outcome (Y) | The metric we believe the treatment moves. In Blue Harbor, rebooking within 12 months (and later, guest satisfaction). | Z ──► Y | continuous, count, or binary | Pick one primary outcome per question; secondary outcomes go in a sensitivity check. | Same as above |
Confounder (X or W) | A cause of both treatment and outcome that, if ignored, makes the treatment-outcome association a lie about causality. | X ─► ZX ─► YZ ─► Y | any type | Adjust / stratify / regress on it, or block it in the DAG. Ignoring it is the most common causal bug. | Simpson’s paradox), P01 correlation vs causation), P04 sensitivity) |
Mediator (M) | A variable on the causal path from treatment to outcome. Part of the effect flows through it. | Z ─► M ─► Y | any type | Do not adjust for it on the main effect — you’d block the very effect you’re trying to measure. Use it for mediation / mechanism analysis instead. | P09 counterfactuals), P10 end-to-end) |
Collider (C) | A variable caused by both treatment and outcome (or by descendants of them). Conditioning on it opens a spurious path. | Z ─► C ◄─ Y | any type | Avoid unless you’re intentionally studying selection. Conditioning here is a classic “Berkson’s paradox” trap. | Simpson’s paradox), P04 sensitivity) |
| DAG (directed acyclic graph) | A picture of assumed causal relationships. Nodes are variables; arrows are direct causes; no cycles allowed. | the whole diagram | structure | Sketch it before estimation. The DAG tells you which variables to adjust for and which to leave alone. | P01), P10) |
| Estimand | The quantity you want to know — written in math, not code. A precise sentence about a target population. | E[Y(z=1) − Y(z=0)] | a scalar target | Specify it before choosing an estimator. “ATE”, “ATT”, “CATE” are all estimands. | P01), P10) |
| ATE (average treatment effect) | The average causal effect of treatment across the whole population: what would happen if everyone flipped from untreated to treated. | E[Y(1) − Y(0)] | real number | The default “first number to report.” | P01), P10) |
| CATE (conditional ATE) | The ATE for a subgroup defined by pre-treatment covariates (e.g., business vs leisure guests). | E[Y(1) − Y(0) | X = x] | function of x | Use it for heterogeneous effects / targeting — “does this policy help business travelers?” | P10), partial dependence / ICE) |
| Identification | The bridge from “what we can observe” to “the estimand we want.” Proves the estimand is recoverable from data + DAG. | estimand = f(observables) given assumptions | proof / argument | Do this before coding an estimator. If it doesn’t identify, no fancy model saves you. | P01), P10) |
| Backdoor criterion | A sufficient rule: if you block every backdoor path (paths into Z) by conditioning on a valid set, the Z ─► Y association is causal. | X ─► Z, X ─► Y ⇒ condition on X | rule on the DAG | Use when you have measured the confounders. Most common identification strategy. | P01), P10) |
| Frontdoor criterion | When you can’t adjust for a confounder directly, but a measured mediator fully transmits the effect — use the mediator. | Z ─► M ─► Y, U ─► Z, U ─► Y | rule on the DAG | Use when an unmeasured U confounds Z─Y but a clean mediator M carries the entire effect. Rare but powerful. | P10) |
| Instrumental variable (IV) | A variable IV that affects treatment but has no direct path to outcome except through treatment. | IV ─► Z ─► YU ─► Z, U ─► Y | any type | Use when there’s an unmeasured confounder but a clean “nudge” (price, distance, random push). | P04 sensitivity), P10) |
| Counterfactual | The outcome a single unit would have had under a different treatment than the one received. | Y(z=0) for a unit with z=1 | per-unit, unobserved | The fundamental object of causal inference — ATE is an average of these. | P09 counterfactuals), P10) |
| SUTVA (stable unit treatment value assumption) | No interference between units and no hidden versions of the treatment. | (assumption, not a DAG node) | assumption | Check it before pooling — e.g., one guest’s policy doesn’t spill over onto another’s behavior. | P01), A/B testing) |
| Positivity | Every subgroup defined by covariates has a nonzero chance of receiving each treatment level. | 0 < P(Z=1 | X=x) < 1 | assumption | Without it, you can’t estimate CATE for that subgroup — there’s no data to compare against. | P10) |
| Consistency | The outcome you observe for a unit equals the potential outcome under the treatment they actually got. | Y = Y(z) when Z = z | assumption | It breaks if “treatment = 1” means different things for different people. Define the treatment sharply. | P01), P10) |
| Exchangeability | Treated and untreated groups are comparable — would have had the same outcomes on average if treated the same. | Y(0) ⊥ Z (or ⊥ Z | X for conditional) | assumption | The “no unmeasured confounding” assumption. The most consequential one in any causal study. | P04 sensitivity), P10) |
The Ladder of Causation (Pearl)
Pearl frames causal reasoning as three nested rungs. Each one is strictly more than the one below.
- Seeing (association) —
P(Y | Z = z). What’s the pattern in observed data? This is what regression and most ML report by default. Question: “What if I see Z = 1?” - Doing (intervention) —
P(Y | do(Z = z)). What would happen if I forced Z to a value, cutting incoming arrows? Question: “What if I do Z = 1?” - Imagining (counterfactual) —
Y(z = z') for a unit with Z = z. What would have happened for this specific person under a different treatment? Question: “What if I had done Z = 0 instead?”
The ladder matters because each rung needs more assumptions, more structure, and more machinery. A predictive ML model lives on rung 1. An A/B test answers a rung-2 question by running a real do(). The Blue Harbor observational study wants a rung-2 answer but only has rung-1 data — so it leans on DAGs, identification, and assumptions to climb.
Seeing, Doing, Imagining — formal version
| Plain English | Statistical symbol | Python equivalent |
|---|---|---|
| Distribution of Y given we observe Z = z | df[df.Z==z].Y (just filter observed rows) | |
| Distribution of Y given we force Z = z (cut incoming arrows) | requires a model or experiment; not a simple filter | |
| Outcome for unit i under treatment z, even if their actual treatment was z’ | or | unobservable for the “other” treatment — fundamental missing-data problem |
| ATE = average of the difference in two potential outcomes | np.mean(Y_if_treated - Y_if_untreated) (in counterfactual land) | |
| Conditional ATE | stratify by X, compute ATE per stratum |
The whole game of observational causal inference is: given only , can I recover ? The DAG and assumptions say when the answer is yes.
Which concept for which problem? (decision tree)
Use this to figure out which tool in this glossary applies to your situation.
- I have a question about a policy I could change.
- Is it a randomized experiment you can run? → It’s an A/B test; the randomization guarantees exchangeability. (A/B testing))
- It’s observational (no randomization) → keep going.
- Do you have a guess at the causal structure? → Draw a DAG.
- Are there common causes of treatment and outcome? → Confounder(s); apply the backdoor criterion.
- Is the effect fully transmitted through a measured mediator? → consider the frontdoor criterion.
- Is there a “nudge” that affects treatment but not outcome (except through treatment)? → instrumental variable.
- Is the effect different per subgroup? → CATE.
- You don’t know the structure? → you have a prediction problem, not a causal one. Stop here.
- Do you have a guess at the causal structure? → Draw a DAG.
- I have an effect estimate; I want to know if it’s robust.
- How sensitive is the conclusion to unmeasured confounding? → sensitivity analysis (P04)).
- I want to ask “what would have happened to this guest under the other policy?”
- That’s a counterfactual question → P09).
- I want to summarize a model’s behavior for a treated vs untreated group.
- Use partial dependence / ICE to surface model-implied heterogeneity (PDP & ICE)) — but read it as association, not cause, unless your model was built causally.
Worked example — every term in one Blue Harbor scene
The setup, repeated across the series: Maya (data scientist) and Priya (head of analytics) want to know whether Blue Harbor’s 90-day cancellation policy increased rebooking within 12 months. Some hotels adopted it (Z = 1), some didn’t (Z = 0). The observable association is positive but Maya doesn’t trust it — business-heavy city hotels, which already had higher rebooking, were more likely to adopt.
The mini-DAG
segment ────────────────► rebooking
│ ▲
▼ │
policy ────────────────► rebooking
│ ▲
└────────► satisfaction ──────┘
(mediator)
Read it out loud:
segment ─► policyandsegment ─► rebooking: segment is a confounder.policy ─► satisfaction ─► rebooking: satisfaction is a mediator.- If we (wrongly) compared only guests who left a review, then “left a review” would be a collider (
policy ─► reviewed ◄─ rebooking).
The code (one runnable illustration)
import numpy as np
import pandas as pd
rng = np.random.default_rng(42)
n = 4000
# Covariate: guest segment (0 = leisure, 1 = business). Causes both adoption and rebooking.
segment = rng.binomial(1, 0.5, n)
# Treatment: 90-day policy. Business-heavy hotels more likely to adopt.
policy = rng.binomial(1, 0.25 + 0.40 * segment)
# Mediator: post-stay satisfaction score (0-100). Pushed up by policy.
satisfaction = 60 + 8 * policy + 5 * segment + rng.normal(0, 6, n)
# Outcome: rebooking within 12 months. True effect of policy ~ +10pp.
rebooking = rng.binomial(1, 0.15 + 0.15 * segment + 0.10 * policy)
df = pd.DataFrame({"segment": segment, "policy": policy,
"satisfaction": satisfaction, "rebooking": rebooking})
# (a) Naive association -- confounded by segment
naive = df.loc[df.policy == 1, "rebooking"].mean() - df.loc[df.policy == 0, "rebooking"].mean()
print(naive) # ~ 0.178 <-- too high; segment is inflating it
# (b) Backdoor adjustment by stratifying on segment
ate_leisure = df.query("segment == 0 & policy == 1").rebooking.mean() \
- df.query("segment == 0 & policy == 0").rebooking.mean()
ate_business = df.query("segment == 1 & policy == 1").rebooking.mean() \
- df.query("segment == 1 & policy == 0").rebooking.mean()
ate = 0.5 * ate_leisure + 0.5 * ate_business
print(ate) # ~ 0.10 <-- close to the true 0.10 we baked in
The naive number (~17.8 pp) is not the ATE — it’s a biased association. The stratified number (~10 pp) is the backdoor-adjusted ATE and matches the truth because segment was the only confounder and we adjusted for it.
Line by line:
segment = rng.binomial(1, 0.5, n)— 50/50 mix of leisure and business guests. This is the confounder in the DAG.policy = rng.binomial(1, 0.25 + 0.40 * segment)— business hotels are ~40 percentage points more likely to have adopted (25% baseline vs 65% for business). This is the source of confounding:segmentinfluencespolicy.satisfaction = ...— a mediator: the policy changes satisfaction, and satisfaction is part of how rebooking happens. We won’t adjust for it on the main ATE (we’d block part of the effect).rebooking = ...— the outcome. The coefficient0.10 * policyis the true ATE.naive = ...— the seeing rung. It tells us the conditional association, which is not the causal effect becausesegmentis a common cause.- The stratified block — the doing rung. We compute the effect within each segment, then average. This is the backdoor criterion applied by hand: one covariate, one stratum at a time.
The gap between naive and ate is the confounding bias — exactly what the series’ P01 article warns about.
Mapping every term onto this scene
| Term | Where it lives in the Blue Harbor scene |
|---|---|
| Treatment | policy (the 90-day cancellation offer) |
| Outcome | rebooking (rebooked within 12 months) |
| Confounder | segment (leisure vs business) |
| Mediator | satisfaction |
| Collider | would be left_a_review if we filtered to reviewers only |
| DAG | the picture above |
| Estimand | ATE = “average rebooking rate if every hotel had the policy minus if none did” |
| ATE | the ~0.10 number above |
| CATE | ATE for business vs leisure separately (ate_business, ate_leisure) |
| Identification | “We can identify the ATE from observational data because segment blocks the only backdoor path.” |
| Backdoor criterion | “Condition on segment.” |
| Frontdoor criterion | not needed here — would be relevant if segment were unmeasured and satisfaction fully mediated the effect |
| IV | would be “distance to nearest competitor with the policy” or “regional marketing push” if segment were unmeasured |
| Counterfactual | “What would this specific business guest’s rebooking have been if their hotel hadn’t adopted?” — Y_i(0) for a unit we saw with policy = 1 |
| SUTVA | “One guest’s adoption doesn’t change another’s rebooking” — would fail if guests compared policies across hotels and switched |
| Positivity | “Both segments have some hotels with and without the policy.” Without that, CATE for the empty cell is undefined. |
| Consistency | “A hotel labeled policy = 1 really did implement the 90-day offer the same way.” |
| Exchangeability | “Within a segment, treated and untreated hotels would have rebooked at the same rate if treated the same.” This is the assumption we can’t test — P04 (sensitivity)) stress-tests it. |
Edge cases and common mistakes
Adjustment mistakes — the wrong choice of what to condition on:
- Adjusting for a mediator blocks your own effect. If Maya regresses
rebooking ~ policy + satisfaction, the coefficient onpolicyis not the total effect — it’s the direct effect, minus what flows throughsatisfaction. This is the most common analytical mistake in the corpus’s P10 case study. - Conditioning on a collider opens a non-causal path. If you restrict the analysis to guests who left a review, and both the policy and the (re)booking outcome affect the probability of leaving a review, you’ve created a spurious association. Classic “Berkson’s paradox” trap.
- “Control for everything” is a heuristic, not a rule. It works for pre-treatment covariates that aren’t colliders or mediators. Post-treatment covariates are usually trouble. The DAG, not a checklist of available columns, decides the adjustment set.
Assumption violations — the four identifying assumptions failing quietly:
- Positivity violations hide as empty strata. If no leisure-segment hotel adopted the policy, you can’t estimate
CATE(segment = leisure)— and the ATE will be a weighted Frankenstein of “we can identify business, we can’t identify leisure.” Check the support ofpolicy | segmentbefore estimating. - Consistency breaks when the “treatment” is fuzzy. “90-day policy” might mean different things at different hotels (some with fees, some without). Define the treatment so
Y(z)is well-defined for eachz. If two units both haveZ = 1but different actual policies, consistency is violated. - Exchangeability is untestable. You can never prove from data that there’s no unmeasured confounder. That’s why P04 exists: pick a plausible unmeasured confounder, see how strong it would have to be to flip the conclusion, and report that.
- SUTVA breaks in networked settings. If a guest at a treated hotel calls a friend at an untreated hotel and changes their behavior, or if “treatment” leaks through shared marketing, units aren’t independent. In the Blue Harbor setting, this matters if city-pairs share a market.
Estimand mismatches — solving the wrong quantity even when the math is right:
- The ATE is not the policy-relevant quantity if treatment uptake is selective. If only 12% of hotels would ever adopt, the ATT (average treatment effect on the treated) might be more policy-relevant than the ATE. Pick the estimand to match the decision being made — P10) covers this choice.
- CATE is not “the subgroup effect I see in a tree.” It’s the causal effect in a subgroup. A tree split’s leaf difference is an association unless you’ve built the tree to estimate causal effects (e.g., causal forest, T-learner). The PDP/ICE article (here)) is explicitly not causal — keep the distinction clean.
Cross-references
These corpus articles use the vocabulary in this reference:
- Causal inference in Python — P01: Correlation isn’t causation)
- Causal inference in Python — P04: Sensitivity analysis)
- Causal inference in Python — P09: Counterfactual reasoning)
- Causal inference in Python — P10: End-to-end case study on the hotel data)
- Simpson’s paradox: when aggregated data tells the wrong story)
- Partial dependence plots and ICE curves)
- A/B testing: deployed models, shadow deployments, and…)
Further reading
- Pearl, J. (1995). “Causal diagrams for empirical research.” Biometrika, 82(4), 669–688. — the original introduction of the causal-DAG framework and the backdoor criterion.
- Pearl, J. (2009). Causality: Models, Reasoning, and Inference, 2nd ed. Cambridge University Press. — the canonical book; Chapter 1 lays out the Ladder of Causation and Chapter 3 the backdoor and frontdoor criteria.
- Imbens, G. W., & Rubin, D. B. (2015). Causal Inference for Statistics, Social, and Biomedical Sciences. Cambridge University Press. — the potential-outcomes (“Neyman–Rubin”) framework at book length; this is where the counterfactual notation and the SUTVA / consistency / positivity / exchangeability assumptions are stated precisely.
dowhydocumentation — https://py-why.github.io/dowhy/ — the Python library used throughout the Blue Harbor series. Its four-step API (model the DAG, identify the estimand, estimate, refute) mirrors the structure of this glossary exactly.- Hernán, M. A., & Robins, J. M. (2020). Causal Inference: What If. — free online at https://www.hsph.harvard.edu/miguel-hernan/causal-inference-book/. Chapters 1–3 are a gentler complement to Pearl’s formalism and use the same “treatment / outcome / confounder” vocabulary this reference leans on.
Related articles
- Causal Inference Under review
Propensity Scores in Plain English: Matching, Weighting, and When They Fail
Learn how propensity scores fix selection bias in causal inference — through matching, weighting, and the common support trap that makes both methods fail.
- Causal Inference Under review
Instrumental Variables: When You Can't Measure the Confounder Directly
Discover how Instrumental Variables bypass unmeasured confounders using a random nudge and Two-Stage Least Squares to recover unbiased causal effects.
- Causal Inference Under review
Sensitivity Analysis: How Robust Is Your Estimate to an Unmeasured Confounder?
Learn how to stress-test your causal estimates against unmeasured confounders using sensitivity analysis, E-values, and tipping-point plots in DoWhy.
- Causal Inference Under review
Estimating and Validating Causal Effects With DoWhy
Learn how to use DoWhy to identify, estimate, and validate causal effects using backdoor adjustment, multiple estimation methods, and refutation tests.
Looking for something else?
Search every article by title, summary or topic.