AdvancedIndependently reviewed, not yet spot-checked by a human

Confounding, DAGs and what to adjust for

The three conditions a confounder has to meet, how drawing your causal assumptions as a DAG turns "what goes in the model" into a question you can check item by item, and why adjusting for a collider manufactures an association out of nothing — including the collider that happens before the exposure and looks entirely harmless.

What this page answers

The cohort study chapter set out the central difficulty of observational research: the two groups differ before any treatment is given, so an observed association is not a treatment effect. Its answer was to put the measured confounders into a Cox model, with one honest qualifier attached — statistical adjustment can only handle variables you actually measured.

This page goes one step earlier, to the more basic question: among the variables you did measure, which ones belong in the model?

The intuitive answer is “all of them — the more you adjust for, the cleaner it gets”. That intuition is wrong in three situations, and it is wrong in a specific direction: the problem is not that you adjusted too little, it is that the adjustment itself created the bias. Telling those three situations apart cannot be done with p-values, stepwise regression, or AIC. All of those look only at associations in the data, and whether a variable should be adjusted for is a question about causal structure, which the data alone will never answer.

A directed acyclic graph (DAG) is the tool for writing that structure down. It will not find the truth for you. It does exactly one thing: it puts your assumptions out in the open, so that “what should I adjust for” becomes a question you can check line by line instead of a judgement call made by feel.

The three conditions for a confounder

For a variable CC to be a confounder of the exposure AA and the outcome YY, the traditional definition asks for three conditions at once:

  1. CC is associated with the exposure AA — the treated and untreated groups differ on CC
  2. CC is an independent risk factor for YY — even setting AA aside, CC affects the outcome
  3. CC does not lie on the causal path from AA to YY — it is not caused by the exposure, and it is not a way station through which the exposure acts

The third is the one people skip, and it is exactly the line separating a confounder from a mediator. The first two are visible in the data (you can compute a correlation, you can run a regression). The third is not. It is knowledge about timing and mechanism, and it can only come from the clinic, from the literature, and from your understanding of the disease.

Drawing the problem as a DAG

The rules of a DAG fit in one sentence: draw a node for each variable, draw an arrow for each “I believe X directly causes Y”, point every arrow at the consequence, and never let a path loop back on itself (acyclic). An absent arrow is a substantive claim — “I believe there is no direct causal link between these two” — so the places where you cannot draw an arrow matter as much as the places where you can.

Once the graph is drawn, association flows along three kinds of path:

Shape of the pathNameOpen by default?What adjusting for the middle node does
ACYA \leftarrow C \to YFork / common causeOpenCloses it — which is exactly what we want
AMYA \to M \to YChain / mediationOpenCloses it — but what it closes is the effect you meant to estimate
ASYA \to S \leftarrow YCollider / common effectClosedOpens it, manufacturing an association out of nothing

The third row is the least intuitive and the most useful thing in the whole DAG language. A collider path is closed by default, and adjustment opens it. It is the single most important counterexample to “more adjustment is better”.

Four structures, four answers

Each of the four structures was simulated 500 times with 2000 participants per run, and each run fits two models: exposure only (Y ~ A), and exposure plus one more variable (Y ~ A + Z). Every arrow in all four structures was given the same strength, so the only thing that differs between them is the shape.

Four small DAGs. In the first, a confounder C points at both A and Y. In the second, a collider S is pointed at by both A and Y. In the third, a mediator M sits on the path from A to Y. In the fourth, the M-bias structure, Z is pointed at by two unmeasured variables U1 and U2. In each panel a red dashed box marks the variable that was adjusted for.
Four structures; the red dashed box marks the variable that was put into the model, and grey nodes are unmeasured. A has a real effect on Y only in the first and third panels; in the second and fourth the true effect is zero.Plotting script figures/scripts/B6-01-dag.R
set.seed(20260822)
n <- 2000; g <- 0.8      # g = strength of every non-causal arrow, shared by all four

# 1. Confounder: C causes both A and Y; true effect = 1
gen_confounder <- function(n) {
  C <- rnorm(n); A <- g * C + rnorm(n); Y <- 1 * A + g * C + rnorm(n)
  data.frame(A, Y, Z = C)
}
# 2. Collider: A and Y are independent, both cause S; true effect = 0
gen_collider <- function(n) {
  A <- rnorm(n); Y <- 0 * A + rnorm(n); S <- g * A + g * Y + rnorm(n)
  data.frame(A, Y, Z = S)
}
# 3. Mediator: A acts through M; total effect = 0.2 + 0.8 * 0.8
gen_mediator <- function(n) {
  A <- rnorm(n); M <- g * A + rnorm(n); Y <- 0.2 * A + g * M + rnorm(n)
  data.frame(A, Y, Z = M)
}
# 4. M-bias: Z precedes the exposure, but is a common effect of two
#    unmeasured variables; true effect = 0
gen_mbias <- function(n) {
  U1 <- rnorm(n); U2 <- rnorm(n)
  Z <- g * U1 + g * U2 + rnorm(n)
  A <- g * U1 + rnorm(n)
  Y <- 0 * A + g * U2 + rnorm(n)
  data.frame(A, Y, Z)
}

d <- gen_collider(n)
coef(lm(Y ~ A, data = d))["A"]        # unadjusted
coef(lm(Y ~ A + Z, data = d))["A"]    # after adjusting for the collider

Verified with R 4.6.0; base R only, no packages needed

Four panels, each showing density curves for the unadjusted and adjusted estimates across 500 simulations, with a dashed line at the true effect. In the confounder panel the adjusted distribution sits on the true value; in the other three panels the adjusted distribution is clearly displaced from it.
Each panel is the distribution of estimates from 500 repetitions of one structure. Blue is unadjusted, red is with the extra variable in the model, and the black dashed line is the true effect. Only in the first panel is adding the extra variable the right move.Plotting script figures/scripts/B6-01-dag.R
StructureHow it reads clinicallyTrue effectY ~ AY ~ A + ZWhat to do
ConfounderDisease severity decides both who gets the drug and who dies1.00+1.39+1.00Adjust
ColliderBeing admitted is caused by the exposure and by the outcome0.000.00−0.39Do not adjust
MediatorThe drug works by lowering blood pressure0.84+0.84+0.20Do not adjust (unless the direct effect is what you want)
M-biasA variable measured before the exposure that is a common effect of two unmeasured causes0.000.00−0.12Do not adjust

Only in the first row does the extra variable improve anything. In the other three, the variable you added took an unbiased estimate and broke it.

Colliders: adjustment manufactures an association

The second row is worth stopping on. The exposure and the outcome are completely independent in the simulation — the true effect is set to zero — and the unadjusted estimate is +0.001. After adjustment it becomes −0.388. In a single run of the simulation the confidence interval for that association runs from -0.455 to -0.372, nowhere near zero, with a p-value too small for the output to print.

Two variables with nothing whatsoever to do with each other look strongly related, purely because one common effect was added to the model.

Here is why, intuitively. Suppose there are only two reasons to be admitted to hospital (SS): the exposure, and the disease itself. Now look only at admitted patients — among them, anyone who was not exposed must have been admitted because their disease was more severe. So within admitted patients, “unexposed” and “severely ill” travel together, and that association does not exist in the general population at all. You created it by choosing whom to look at.

M-bias: it happens before the exposure, and you still must not adjust for it

That test invites a convenient shortcut: “adjust only for things that happened before the exposure, and you can never hit a collider.” The shortcut is right most of the time. M-bias is the rest of the time.

The fourth DAG has this structure. Two things go unmeasured: U1U_1 (say, a tendency toward health-seeking behaviour) and U2U_2 (say, undiagnosed latent disease). U1U_1 influences whether a patient receives the exposure, U2U_2 influences the outcome, and both of them influence the same variable ZZ (say, a lab value measured years earlier).

ZZ clearly happened before the exposure, it is associated with the exposure, and it is associated with the outcome — run it through the traditional three-condition checklist and it looks like a textbook confounder. In fact it is a collider for U1U_1 and U2U_2. Adjusting for it opens the path AU1ZU2YA \leftarrow U_1 \to Z \leftarrow U_2 \to Y, which was closed: the true effect is zero, and the adjusted estimate is −0.124.

Mediators: you adjust away the thing you wanted to estimate

The third row is a different kind of problem. It is not bias — it is answering a different question.

In the simulation the drug acts along two paths: a direct one, and one through a mediator (blood pressure). The total effect is 0.84; the unadjusted model estimates 0.841, which is accurate. Put the mediator in and the estimate falls to 0.200 — which is precisely the direct effect.

Nobody miscalculated. The two numbers answer different questions:

  • Total effect: “if I give this drug, how much does the outcome change?” — the number a clinical decision needs
  • Direct effect: “with the blood-pressure pathway taken out, how much of the drug’s action is left?” — the number a mechanistic study needs

The backdoor criterion in plain words

With those three path shapes in hand, “what should I adjust for” becomes a criterion you can execute mechanically. A backdoor path is any path that starts at the exposure with an arrow pointing into the exposure (the arrow leaves “backwards”) and ends at the outcome. The association such a path carries is not causal; it is noise.

The plain-language backdoor criterion is three sentences:

  1. Find every backdoor path
  2. Choose a set of variables such that every backdoor path is blocked — either a non-collider on the path has been adjusted for, or the path contains a collider that has not been adjusted for
  3. That set must contain no descendant of the exposure (anything the exposure causes, mediators included)

A set of variables satisfying all three is a valid adjustment set. Two things about it run against intuition:

  • There can be more than one valid adjustment set, and the valid one is not necessarily the largest
  • Adding a variable can turn a valid set into an invalid one — which is exactly what M-bias is

You do not have to do this by hand: the dagitty package (there is also a web version) takes the graph and returns every minimal valid adjustment set, and the next section shows exactly how. What still needs a human is getting the arrows right, and no tool can do that part for you.

Handing the DAG to a machine: from picture to adjustment set

The previous section said you do not have to work this out by hand. This section is that promise paid off — write the same picture as code and let it produce the answer.

The dagitty syntax is close to just typing the arrows out. What follows is the confounder structure from the top left of this page’s first figure, character for character:

library(dagitty)

g <- dagitty('dag {
  A [exposure,pos="0,0"]
  Y [outcome,pos="1,0"]
  C [pos="0.5,-0.85"]
  A -> Y
  C -> A
  C -> Y
}')

adjustmentSets(g)                      # every minimal sufficient adjustment set
impliedConditionalIndependencies(g)    # what this graph claims you will not see

Verified with dagitty 0.3.4. The web version at dagitty.net takes exactly the same syntax, so the string below can be pasted straight in.

The pos= coordinates affect layout only, never the computation. They are there so that pasting the string into dagitty.net gives you the same picture as the figure above. (The y values are negative because the web version points its y axis downwards.)

What the four structures answer

Running all four structures from this page through adjustmentSets():

StructureWhat instinct adjusts foradjustmentSets()Was instinct right
ConfounderC{ C }Yes
ColliderS{ }No
MediatorM{ }No
M-biasZ{ }No

Only the confounder structure has instinct and tool agreeing. For the other three the tool returns { }adjust for nothing.

That is the same conclusion the simulations earlier on this page reached, arrived at by a different route. The simulations answer “how far does the estimate move if you adjust”; this answers “the graph never asked you to adjust in the first place”. The second kind of evidence needs no data at all.

A DAG can be refuted by data

impliedConditionalIndependencies() lists the places where the graph claims you will find no association. For both the collider and the M-bias structures it returns the same line, A _||_ Y — exposure and outcome should be unrelated, because neither of those graphs contains a causal arrow from A to Y, and the one path that does join them in the M-bias graph runs through the collider Z, which stays closed for as long as you do not adjust for it.

That is useful because you can check it against data. If A and Y are plainly associated in the data, the data is not the problem: your graph is wrong — a missing arrow, or one pointing the wrong way.

The confounder and mediator graphs return an empty list. On their three observed nodes those graphs are complete — every pair is joined by a direct arrow — and a complete graph forbids nothing, so there is nothing left for data to contradict. The asymmetry is worth remembering: a DAG that forbids nothing is a DAG that cannot be shown to be wrong.

So what should you adjust for

Everything above, compressed into a checklist you can take into a meeting:

Role of the variableHow to recognise itInto the model?
ConfounderPrecedes the exposure, affects both exposure and outcome, not on the causal pathYes — this is what adjustment exists for
Predictor of the outcome onlyAffects the outcome, unrelated to the exposureFine to include; improves precision, creates no bias
Predictor of the exposure onlyAffects the exposure, not the outcomeUsually leave out; it costs precision and amplifies residual bias
MediatorComes after the exposure; the way station through which it actsLeave out (unless the direct effect is what you want, with a full mediation analysis)
ColliderAffected by both exposure and outcomeNever include, and never select the sample on it either
Pre-exposure collider (M-bias)A common effect of two unmeasured causesLeave out, but the cost depends on arrow strengths you cannot know
Instrumental variableAffects the exposure, and affects the outcome only through the exposureNot as a covariate — it has its own estimator; see instrumental variables

From the DAG to an actual analysis

A DAG tells you which paths need blocking. It does not tell you how to block them. There are several ways, each with its own price, and the next few pages take them one at a time:

The first three share one prerequisite: the confounders were measured. Matching and weighting can do nothing at all about the grey, unmeasured nodes on a DAG — they are simply different ways of using the variables you already have. The cohort study chapter said this once; it is worth saying again.

Common misuses

MisuseWhy it is wrong
“The more you adjust for, the better”Colliders and mediators make the estimate worse, not better
Selecting covariates by univariable p-value or stepwise regressionWhether to adjust is a question about causal structure; associations in the data cannot answer it
“It differs significantly between groups, so we adjusted for it”That satisfies only the first of the three conditions
Adjusting for a variable measured after treatment startedIt is usually a mediator or a collider, and both do damage
Adjusting away a mediator and still calling the estimate a treatment effectWhat you estimated is the direct effect, not the total effect
Analysing only inpatients, or only responders, without treating it as an issueSelecting on a collider and adjusting for one are the same operation
“This variable precedes the exposure, so adjusting for it must be safe”M-bias is the counterexample to that rule
Claiming causation because the model was adjustedUnmeasured confounding shows up in no statistic
Adjusting for an instrumental variable as if it were a covariateIt amplifies residual bias; its correct use is a different estimator entirely
Treating a finished DAG as proof of the causal structureA DAG makes your assumptions explicit; it does not verify them

Reproducing every number on this page

/opt/homebrew/bin/Rscript figures/scripts/B6-01-dag.R

Read the figure

The answer comes from the same statistical output that produced this page's figures, not from a number typed in beside them.

The simulation makes exposure and outcome completely independent, so the true effect is 0. Across 500 replications, putting their common consequence into the model moves the mean estimate somewhere else. Which sentence describes that move?

Show the answer and why

Correct answer: The adjusted mean over 500 replications is -0.388, an association adjustment opened up — the data-generating process never had it

The unadjusted mean is 0.001, sitting on the true effect the simulation was given. Adding the common consequence drags the mean of 500 replications to -0.388, and that is not noise: in a single replication the upper limit of the interval, -0.372, already lies entirely to the left of zero, so it neither covers zero nor leaves the conclusion where it was. A collider path is closed by default and adjustment opens it, so two variables with no relationship at all come to look strongly related. The same move wears other clothes: restricting to inpatients, or to people who returned the questionnaire, is the identical operation on the DAG.

In the simulation the drug acts along two paths and the total effect is 0.84. Putting the mediator into the model pulls the estimate down. Which sentence describes that drop?

Show the answer and why

Correct answer: The adjusted estimate is 0.200, the direct effect left once the mediated path is closed, which answers a mechanism question rather than the total one

Unadjusted the model estimates 0.841, right on the total effect; with the mediator in, it estimates 0.200, which is exactly the direct path the simulation was built with. Nothing here was miscalculated — the question changed. The total effect answers what happens if you give the drug; the direct effect answers what is left after the mediated route is closed off. The value -0.640 is that row's bias column, the gap between estimate and truth rather than a coefficient any model printed, and reading the bias column as the estimate yields the opposite conclusion, that the drug is harmful. As for collinearity: a mediator being correlated with the exposure is precisely why the exposure coefficient must move, and that movement is the path being closed.

The confounder row shows an unadjusted mean estimate of 1.390 against a true effect of 1. Which sentence describes the gap above the truth?

Show the answer and why

Correct answer: The gap is 0.390, because a common cause makes people already prone to the outcome likelier to be exposed, charging that difference to the exposure

The 1.390 is the unadjusted mean, the 1.000 is the mean once the common cause is in the model, and the 0.390 between them is the column the table calls bias. A common cause decides both who gets exposed and who has the outcome, so a difference the two groups already had is charged to the exposure's account; close that fork and the estimate returns to 1. The 0.021 is the standard deviation across the 500 replications of the unadjusted row, an order of magnitude smaller than 0.390, so the gap cannot be simulation noise — which is also why bias is read off the mean of repeated replications rather than off any single estimate. And adjustment did not strip the effect out: the adjusted mean does not sit below the truth, it sits on it.

Hand the mediator graph to dagitty's adjustmentSets(). What comes back?

Show the answer and why

Correct answer: It returns { }, so this graph asks for no adjustment at all and the mediator is in no valid set

The third clause of the backdoor criterion is explicit: a valid adjustment set may not contain a descendant of the exposure, and a mediator is exactly something the exposure caused. So the answer is the empty set, and the tool and the simulation reach the same conclusion by different routes — the simulation says how far adjustment biases the estimate, the tool says the graph never asked for the adjustment. A set containing a variable is the confounder graph's answer, and carrying it over here swaps the conclusions of two different graphs. The variable named as one that must be adjusted for is an input you supplied, not the tool's output; the tool never hands back a descendant of the exposure. Note that the tool answers the graph you drew: draw it wrong and the answer is wrong, confidently.

The bias in the M-bias row is far smaller than in the collider row. Some argue from this that an uncertain variable is better adjusted for than left out. Which sentence best states the problem with that argument?

Show the answer and why

Correct answer: Adjusting for Z gives -0.124, and that magnitude is set by four arrows, two of which run to variables you cannot estimate

The true effect is zero. Leaving Z alone gives a mean of -0.001; adjusting for it gives -0.124. That is indeed much smaller than the collider row's -0.388, which is consistent with the position that adjustment is the safer default. Two things go with it: the magnitude is set by the strength of four arrows, and two of those arrows run to unmeasured variables whose strength the data cannot reveal. So the practical conclusion is not whether to adjust but that you have to write down the structure you believe in before you can know what you are betting on. As for the structure not arising in practice: Z occurs before the exposure and is associated with both exposure and outcome, so the traditional three-condition checklist calls it a confounder, which is where the shortcut rule breaks.

In the collider row, one replication gives an adjusted estimate of -0.413 with a 95% interval that excludes zero and a p value too small for the printout. Which sentence describes that p value?

Show the answer and why

Correct answer: The effect the simulation was given is 0.000, and a p value only says the association is hard to produce by sampling error, never where it came from

The true effect was set to 0.000, and yet after adjusting for the collider the association is not merely present but highly significant. A p value asks how easily sampling error could produce an association this large, not whether the association is causal — and a bias reproduced faithfully in every replication makes the p value smaller and the interval narrower, so there is no bridge from far from zero to solid causal evidence. The lower limit of -0.455 says the same thing. The unadjusted model's p value of 0.797 is the one to believe, and not because it is larger: because that model never opened the collider path. Which model to trust is settled by the shape of the graph, not by a p value.

Watch next

Clearing Up Confounding
ENACER Consulting· 4 minFour minutes covering what confounding is. Watch it before the second section of this page.
因果圖 DAG 是什麼?一張圖看穿因果的陷阱
繁中Colon & Code· 6 minThe only short Traditional-Chinese video that tackles DAGs head on; it maps onto the third section here.
Introduction to Causal Graphs
ENLeslie Myint· 6 minA six-minute introduction to the graphical language. Watch the short one first and then decide whether you want the long lecture.
Directed Acyclic Graphs (DAGs)
ENEpidemiology Stuff· 21 minFills in the backdoor criterion and colliders — the full-length version of sections five through eight of this page.
Principles of Epidemiology 05. Causal Inferences, Bias, Confounding, and Interaction
繁中臺大開放式課程 NTU OCW· 63 minA complete lecture in Traditional Chinese from National Taiwan University's open courseware. If you want causal inference taught as a course, this is the textbook version of this page.

Sources and licences

This page is original writing

Report a content problem

The statistics on this site are written by AI and reviewed by AI; a human only spot-checks. What you can see may be what we cannot.

The more specific, the more fixable — e.g. which sentence disagrees with which textbook or paper.

Needed only if you want a reply; reports without it are still read.

Sent along with your report

These are attached automatically. You can drop any of them.