Let's imagine we have data generated according to the DAG

X  ->  y  <- U2
^      ^
|      |
U0 -> U1 

I was running some simulations (below) to work on my intuition and I had some questions about selection control variables in a model in order to reduce the variance of the causal estimate of $X$ in $y$

The models \begin{align} &m_0\!: &&y \sim X + U_0 \\ &m_{01}\!: &&y \sim X + U_0 + U_1 \\ &m_1\!: &&y \sim X + U_1 \\ &m_{12}\!: &&y \sim X + U_1 + U_2 \end{align} All give an unbiased estimate of the causal effect of $X$ on $y$, however, in terms of the variance of the estimate, we have

$$ m_{12} \lt m_1 \lt m_{01} \lt m_0 $$

My observations are that conditional on the backdoor paths being blocked, controlling for variables "adjacent" to $y$ is better than controlling for variables farther away from $y$ and that controlling for multiple variable on a backdoor path is worse than only controlling for the variable ($m_{01}$ vs $m_1$)

I was wondering what the explanation for these phenomena is? It seems that DAGs can be very useful for this sort of model selection/experimental design but I haven't really found any DAG based resources.

# library(ggplot2)

n_sims <- 1000
n <- 100

simulate <- function(){
  u0 <-  rnorm(n)
  x <- u0 + rnorm(n, sd=0.5)
  u1 <- u0 + rnorm(n, sd=0.5)
  u2 <- rnorm(n)
  y <- x + u1 + u2 +  rnorm(n)
  models <- list(
    m0 =lm(y ~ x + u0 ),
    m1 = lm(y ~ x + u1),
    m12 = lm(y ~ x + u1 + u2),
    m01 = lm(y ~ x + u0 + u1)
  bind_rows(lapply(models, tidy), .id = 'model')

results <- 
  replicate(n_sims, simulate(), simplify = FALSE) %>% 
  bind_rows(.id = 'iter')
# results %>%
#   filter(term == 'x') %>% 
#   ggplot() +
#   geom_histogram(aes(estimate)) +
#   facet_wrap(~model)

results %>% 
  filter(term == 'x') %>% 
  group_by(model, term) %>% 
#> `summarise()` has grouped output by 'model'. 
#>               You can override using the `.groups` argument.
#> # A tibble: 4 × 3
#> # Groups:   model [4]
#>   model term  `var(estimate)`
#>   <chr> <chr>           <dbl>
#> 1 m0    x              0.0923
#> 2 m01   x              0.0819
#> 3 m1    x              0.0452
#> 4 m12   x              0.0231

Created on 2022-01-16 by the reprex package (v2.0.1)

  • 1
    $\begingroup$ Please consider using base R, & commenting it extensively, when illustrating posts here with R code. Not everyone who will come to this page will be familiar with R, & not all of those will be able to read tidy-code. This is a Q&A site for statistics, not R. $\endgroup$ Jan 17 at 18:43

1 Answer 1


In general, if a variable is strongly related to the response, controlling for it reduces the error variance, and thus increases power and precision. That doesn't have anything to do with DAGs—it's basic multiple regression. Controlling for U1 is better than U0 because it will be more strongly correlated with Y, leading again to lower error variance, etc. Controlling for one of them is necessary to block the backdoor path & achieve unbiasedness, but that's the only part that has anything to do with causal inference. As for controlling for both, that will lead to some collinearity. The same argument holds for controlling for X as opposed to U0 (in addition to the fact that learning about X is also be the point of the analysis).

The collinearity of U0 and U1 won't increase the variance of the coefficient estimates of the other variables, but once you've got U1, U0 doesn't add anything, and since it's correlated, it makes the standard error of U1 larger. In addition to providing no further explanatory value, it consumes a degree of freedom, which makes the error variance of the whole model slightly larger. Again, the same argument applies to U1 -> X.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.