In this scenario, we have a binary mediator \(M\), a binary outcome \(Y\), and no effect modification. The sample size is 50 and there are 3 covariates.
dat <- cma_sampledata(N = 50, L=3, P=3, scenario=2, seed=7)
head(dat$data, n = 3L)
#> z1 z2 z3 M x1 x2 x3 y
#> 1 2.2767428 0.1432685 0.7973699 1 -0.3556944 2.02334405 -1.477592 1
#> 2 -1.0893537 -0.0944783 0.4035083 0 1.0973004 0.86249250 -2.973256 1
#> 3 -0.6389109 0.2491581 -0.1243989 0 -0.9066920 -0.02490949 -1.339762 0
dat = dat$data
let \(A\) be a \(n\)-by-\(L\) matrix containing an exposure mixture
comprised of \(L\)
elements,E.M
and E.Y
be effect modifiers of
exposure-mediator and exposure-outcome relationship respectively, \(y\), a vector of outcome data, and \(m\), a vector of mediator data.
Z.M <- cbind(A,E.M)
Z.Y <- cbind(A,E.Y)
Let Z.M
be the exposures and effect modifers
E.M
and let Z.Y
be the exposures and effect
modifers E.Y
, create one more matrix containing the
exposures, effect modifier Z.Y
and mediator, precisely in
that order.
Zm.Y <- cbind(Z.Y,m)
NOTE: the last column of the Zm.Y
matrix must
be your mediator in order for the functions to work properly.
A <- cbind(dat$z1, dat$z2, dat$z3)
X <- cbind(dat$x1, dat$x2, dat$x3)
y <- dat$y
m <- dat$M
E.M <- NULL
E.Y <- dat$x2
Z.M <- cbind(A,E.M)
Z.Y <- cbind(A, E.Y)
Zm.Y <- cbind(Z.Y, m)
set.seed(1)
fit.y <- kmbayes(y=y, Z=Zm.Y, X=X, iter=10000, verbose=TRUE, varsel=FALSE)
#save(fit.y,file="bkmr_y.RData")
set.seed(2)
fit.y.TE <- kmbayes(y=y, Z=Z.Y, X=X, iter=10000, verbose=TRUE, varsel=FALSE)
#save(fit.y.TE,file="bkmr_y_TE.RData")
set.seed(3)
fit.m <- kmbayes(y=m, Z=Z.M, X=X, iter=10000, verbose=TRUE, varsel=FALSE)
#save(fit.m,file="bkmr_m.RData")
Mean level of confounders:
We define the change in exposure for which you want to estimate the
mediation effects: in this example, we will consider a change in all
exposures from their 25th to 75th percentiles, fixing age
(E.Y
) at testing to its 10th and 90th percentiles. However,
this contrast can be anything.
Note: If modifiers are considered, you should fix the levels of the modifiers
astar <- c(apply(A, 2, quantile, probs=0.25))
a <- c(apply(A, 2, quantile, probs=0.75))
e.y10 = quantile(E.Y, probs=0.1)
e.y90 = quantile(E.Y, probs=0.9)
The index of the MCMC iterations to be used for inference:
sel<-seq(5000,10000,by=10)
Estimate the TE for a change in the exposures from \(a^*\) to \(a\) fixing Effect modifier at testing to its 10th percentile or 90th percentile:
e.y10 = quantile(E.Y, probs=0.1)
e.y90 = quantile(E.Y, probs=0.9)
TE.ey10 <- TE.bkmr(a=a, astar=astar, e.y = e.y10, fit.y.TE=fit.y.TE, X.predict=X.predict, alpha=0.05, sel=sel, seed=122)
TE.ey90 <- TE.bkmr(a=a, astar=astar, e.y = e.y90, fit.y.TE=fit.y.TE, X.predict=X.predict, alpha=0.05, sel=sel, seed=122)
Look at the posterior mean, median, and 95% CI for TE:
TE.ey10$est
#> mean median lower upper sd
#> TE 0.3241404 0.3244238 0.01677121 0.6159663 0.1536497
TE.ey90$est
#> mean median lower upper sd
#> TE 0.430469 0.4243573 0.07051303 0.7911519 0.1731175
plotdf <- as.data.frame(TE.ey10$est)
plotdf["Effect"] <- rownames(plotdf)
ggplot(plotdf, aes(Effect, mean, ymin = lower, ymax = upper)) +
geom_pointrange(position = position_dodge(width = 0.75)) + coord_flip()
Estimate the CDE for a change in the exposures from \(a^*\) to \(a\), fixing the mediator at its 10th, 50th, and 75th percentile and the effect modifier at testing at its 10th percentile:
CDE.ey10 <- CDE.bkmr(a=a, astar=astar, e.y = e.y10, m.quant=c(0.1,0.5,0.75), fit.y=fit.y, alpha=0.05, sel=sel, seed=777)
#> [1] "Running 3 mediator values for CDE:"
#> [1] "1 out of 3"
#> [1] "2 out of 3"
#> [1] "3 out of 3"
CDE.ey90 <- CDE.bkmr(a=a, astar=astar, e.y = e.y90, m.quant=c(0.1,0.5,0.75), fit.y=fit.y, alpha=0.05, sel=sel, seed=777)
#> [1] "Running 3 mediator values for CDE:"
#> [1] "1 out of 3"
#> [1] "2 out of 3"
#> [1] "3 out of 3"
Look at the posterior mean, median, and 95% CI for the CDEs:
CDE.ey10$est
#> mean median lower upper sd
#> CDE10% 0.3092927 0.2999788 -0.043365129 0.6917523 0.1796301
#> CDE50% 0.3609607 0.3402882 -0.005062313 0.7992176 0.1939582
#> CDE75% 0.3609607 0.3402882 -0.005062313 0.7992176 0.1939582
CDE.ey90$est
#> mean median lower upper sd
#> CDE10% 0.4085146 0.4027476 0.02286425 0.8323147 0.2007848
#> CDE50% 0.4562550 0.4515731 0.08655578 0.9197106 0.2095806
#> CDE75% 0.4562550 0.4515731 0.08655578 0.9197106 0.2095806
Plotting:
plotdf <- as.data.frame(CDE.ey10$est)
plotdf["Effect"] <- rownames(plotdf)
ggplot(plotdf, aes(Effect, mean, ymin = lower, ymax = upper )) +
geom_pointrange(position = position_dodge(width = 0.75)) + coord_flip()
Estimate the TE, NDE and NIE for a change in the exposures from \(a^*\) to \(a\) fixing age at testing to its 90th percentile.
Note: this step takes a while to run and will take longer for more
complex BKMR fits, longer sel
vectors and larger.
mediationeffects.ey10 <- mediation.bkmr(a=a, astar=astar, e.y = e.y10, fit.m=fit.m, fit.y=fit.y, fit.y.TE=fit.y.TE, X.predict.M=X.predict, X.predict.Y=X.predict, alpha=0.05, sel=sel, seed=22, K=10)
mediationeffects.ey90 <- mediation.bkmr(a=a, astar=astar, e.y = e.y90, fit.m=fit.m, fit.y=fit.y, fit.y.TE=fit.y.TE, X.predict.M=X.predict, X.predict.Y=X.predict, alpha=0.05, sel=sel, seed=22, K=10)
Look at the posterior mean, median, and 95% CI for the TE, NDE, and NIE
mediationeffects.ey10$est
#> mean median lower upper sd
#> TE 0.30916635 0.314290915 -0.02660571 0.5727188 0.1549434
#> NDE 0.29834270 0.301233360 -0.33291485 0.9103089 0.3239850
#> NIE 0.01082364 0.004102463 -0.59770537 0.6713659 0.3193340
#> CDE10% 0.28813715 0.295343850 -0.10165967 0.6682970 0.1904052
#> CDE50% 0.34321913 0.342000447 -0.04373672 0.7398543 0.1917391
#> CDE75% 0.34321913 0.342000447 -0.04373672 0.7398543 0.1917391
mediationeffects.ey90$est
#> mean median lower upper sd
#> TE 0.415301283 0.40574600 0.11468494 0.7543082 0.1656023
#> NDE 0.422781310 0.40948509 -0.27526006 1.1759479 0.3487023
#> NIE -0.007480027 -0.01404017 -0.74070549 0.7414162 0.3649172
#> CDE10% 0.386433102 0.39061531 -0.03306667 0.8217995 0.2082319
#> CDE50% 0.437912375 0.43447120 0.05164739 0.8499772 0.2022834
#> CDE75% 0.437912375 0.43447120 0.05164739 0.8499772 0.2022834
Plotting
plotdf <- as.data.frame(mediationeffects.ey10$est)
plotdf["Effect"] <- rownames(plotdf)
ggplot(plotdf, aes(Effect, mean, ymin = lower, ymax = upper )) +
geom_pointrange(position = position_dodge(width = 0.75)) + coord_flip()
riskSummary10 = TERiskSummaries.CMA(fit.TE = fit.y.TE, e.y=e.y10, e.y.name = "E.Y", sel=sel)
ggplot(riskSummary10,
aes(quantile,
est,
ymin = est - 1.96 * sd,
ymax = est + 1.96 * sd)) +
geom_pointrange()
riskSummary90 = TERiskSummaries.CMA(fit.TE = fit.y.TE, e.y=e.y90, e.y.name = "E.Y", sel=sel)
ggplot(riskSummary90,
aes(quantile,
est,
ymin = est - 1.96 * sd,
ymax = est + 1.96 * sd)) +
geom_pointrange()
Since there’s no effect modification, the two above figures are similar.
# CDE
CDEriskSummary10 = CDERiskSummaries.CMA(fit.y = fit.y, e.y = e.y10, e.y.name = "E.Y", m.name = "m", sel = sel)
ggplot(CDEriskSummary10, aes(quantile, est, ymin = est - 1.96*sd,
ymax = est + 1.96*sd, col = m)) +
geom_pointrange(position = position_dodge(width = 0.75))
CDEriskSummary90 = CDERiskSummaries.CMA(fit.y = fit.y, e.y = e.y90, e.y.name = "E.Y", m.name = "m", sel = sel)
ggplot(CDEriskSummary90, aes(quantile, est, ymin = est - 1.96*sd,
ymax = est + 1.96*sd, col = m)) +
geom_pointrange(position = position_dodge(width = 0.75))
Since there’s no effect modification, the two above figures are similar. ## Single-predictor health risks
risks.singvar10 = SingVarRiskSummaries.CMA(BKMRfits = fit.y.TE, which.z = 1:3,
e.y=e.y10, e.y.names="E.Y",
sel=sel)
plot_singvar10 <- ggplot(risks.singvar10, aes(variable, est, ymin = est - 1.96*sd, ymax = est + 1.96*sd, col = q.fixed)) + theme(legend.position="none")+
geom_pointrange(position = position_dodge(width = 0.5)) +
coord_flip()
risks.singvar90 = SingVarRiskSummaries.CMA(BKMRfits = fit.y.TE, which.z = 1:3,
e.y=e.y90, e.y.names="E.Y",
sel=sel)
plot_singvar90 <- ggplot(risks.singvar90, aes(variable, est, ymin = est - 1.96*sd, ymax = est + 1.96*sd, col = q.fixed)) +
geom_pointrange(position = position_dodge(width = 0.5)) +
coord_flip()
ggarrange(plot_singvar10, plot_singvar90, ncol=2, nrow=1)
Since there’s no effect modification, the two above figures are similar.
CDErisks.singvar10 = CDESingVarRiskSummaries.CMA(BKMRfits = fit.y,
e.y=e.y10, e.y.names="E.Y", m.name = "m",
sel=sel)
plotCDE10 <- ggplot(CDErisks.singvar10, aes(variable, est, ymin = est - 1.96*sd,
ymax = est + 1.96*sd, col = q.fixed, linetype = m.fixed)) +
geom_pointrange(position = position_dodge(width = 0.5)) +theme(legend.position="none")+
coord_flip()
CDErisks.singvar90 = CDESingVarRiskSummaries.CMA(BKMRfits = fit.y,
e.y=e.y90, e.y.names="E.Y", m.name = "m",
sel=sel)
plotCDE90 <- ggplot(CDErisks.singvar90, aes(variable, est, ymin = est - 1.96*sd,
ymax = est + 1.96*sd, col = q.fixed, linetype = m.fixed)) +
geom_pointrange(position = position_dodge(width = 0.5)) +
coord_flip()
ggarrange(plotCDE10, plotCDE90, ncol=2, nrow =1)
Since there’s no effect modification, the two above figures are similar.