X
and Y
while controlling for W
:X
is explained by W
, and subtract it out. Call the result the residual part of X
.Y
is explained by W
, and subtract it out. Call the result the residual part of Y
.X
and the residual part of Y
.Y
across values of X
df <- tibble(w = rnorm(100)) %>%
mutate(x = 2*w + rnorm(100)) %>%
mutate(y = 1*x + 4*w + rnorm(100))
cor(df$x,df$y)
## [1] 0.9479742
df <- df %>% group_by(cut(w,breaks=5)) %>%
mutate(x.resid = x - mean(x),
y.resid = y - mean(y))
cor(df$x.resid,df$y.resid)
## [1] 0.7367752
X
and Y
reflects both X->Y
and X<-W->Y
X
and Y
that W
explains to get rid of X<-W
and W->Y
, blocking X<-W->Y
and leaving X->Y
df <- tibble(w = rnorm(100),v=rnorm(100)) %>%
mutate(x = 2*w + 3*v + rnorm(100)) %>%
mutate(y = 1*x + 4*w + 1.5*v + rnorm(100))
cor(df$x,df$y)
## [1] 0.9340934
df <- df %>% group_by(cut(w,breaks=5)) %>%
mutate(x.resid = x - mean(x),
y.resid = y - mean(y)) %>%
group_by(cut(v,breaks=5)) %>%
mutate(x.resid2 = x.resid - mean(x.resid),
y.resid2 = y.resid - mean(y.resid))
cor(df$x.resid2,df$y.resid2)
## [1] 0.7419072