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(dplyr)
library(broom)
# 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(var(estimate))
#> `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)