mr_mean_ivw <- function(d)
{
d <- subset(d, mr_keep)
stopifnot(nrow(d) >= 1)
b_exp <- d$beta.exposure
b_out <- d$beta.outcome
se_exp <- d$se.exposure
se_out <- d$se.outcome
ratios <- b_out / b_exp
stopifnot(length(unique(d$id.exposure)) == 1)
stopifnot(length(unique(d$id.outcome)) == 1)
id.exposure = d$id.exposure[1]
id.outcome = d$id.outcome[1]
if(nrow(d) == 1)
{
res <- mr_wald_ratio(b_exp, b_out, se_exp, se_out)
out <- dplyr::tibble(
id.exposure = id.exposure,
id.outcome = id.outcome,
method = "Wald ratio",
nsnp = nrow(d),
b=res$b,
se=res$b,
ci_low=b-se*1.96,
ci_upp=b+se*1.96,
pval=stats::pt(abs(b/se), 1, lower.tail=FALSE) * 2
)
return(list(estimates=out))
}
unw <- summary(stats::lm(b_out ~ -1 + b_exp))
unw_out <- dplyr::tibble(
id.exposure = id.exposure,
id.outcome = id.outcome,
method = "Simple mean",
nsnp = nrow(d),
b = unw$coefficients[1],
se = unw$coefficients[2],
ci_low=b-se*1.96,
ci_upp=b+se*1.96,
pval=stats::pt(abs(b/se), nrow(d)-1, lower.tail=FALSE) * 2
)
weights1 <- sqrt(b_exp^2 / se_out^2)
y1 <- ratios * weights1
ivw1 <- stats::lm(y1 ~ -1 + weights1)
weights2 <- sqrt(((se_out^2 + stats::coefficients(ivw1)[1]^2 * se_exp^2) / b_exp^2)^-1)
y2 <- ratios * weights2
ivw2 <- summary(stats::lm(y2 ~ -1 + weights2))
ivwoutliers <- dplyr::tibble(id.exposure = id.exposure, id.outcome = id.outcome, SNP=d$SNP, Qj=weights2^2 * (ratios - stats::coefficients(ivw2)[1])^2, Qpval=stats::pchisq(Qj,1,lower.tail=FALSE))
Qivw2 <- sum(ivwoutliers$Qj)
Qivw2pval <- stats::pchisq(Qivw2, nrow(d)-1, lower.tail=FALSE)
# Collate
re_out <- dplyr::tibble(
id.exposure = id.exposure,
id.outcome = id.outcome,
method = c("RE IVW"),
nsnp = nrow(d),
b = c(ivw2$coefficients[1]),
se = c(ivw2$coefficients[2]),
ci_low = b - se * 1.96,
ci_upp = b + se * 1.96,
pval = stats::pt(abs(b / se), nrow(d)-1, lower.tail=FALSE) * 2
)
fe_out <- re_out
fe_out$se <- fe_out$se / max(1, ivw2$sigma)
fe_out$pval <- stats::pnorm(abs(fe_out$b / fe_out$se), lower.tail=FALSE) * 2
fe_out$method <- c("FE IVW")
out <- dplyr::bind_rows(unw_out, fe_out, re_out)
# Pleiotropy
heterogeneity <- dplyr::tibble(
id.exposure = id.exposure,
id.outcome = id.outcome,
method = c("IVW"),
Q = c(Qivw2),
df = c(nrow(d)-1),
pval = stats::pchisq(Q, df, lower.tail=FALSE)
)
ret <- list(estimates=out, heterogeneity = heterogeneity, outliers=ivwoutliers)
return(ret)
}
mr_mean_egger <- function(d)
{
d <- subset(d, mr_keep)
stopifnot(nrow(d) >= 3)
b_exp <- d$beta.exposure
b_out <- d$beta.outcome
se_exp <- d$se.exposure
se_out <- d$se.outcome
stopifnot(length(unique(d$id.exposure)) == 1)
stopifnot(length(unique(d$id.outcome)) == 1)
id.exposure = d$id.exposure[1]
id.outcome = d$id.outcome[1]
ratios <- b_out / b_exp
weights1 <- sqrt(b_exp^2 / se_out^2)
y1 <- ratios * weights1
# Egger
egger1 <- stats::lm(y1 ~ weights1)
weights2 <- sqrt(((se_out^2 + stats::coefficients(egger1)[2]^2 * se_exp^2) / b_exp^2)^-1)
y2 <- ratios * weights2
egger2 <- summary(stats::lm(y2 ~ weights2))
eggeroutliers <- dplyr::tibble(
SNP=d$SNP,
Qj = weights2^2 * (ratios - stats::coefficients(egger2)[1,1] / weights2 - stats::coefficients(egger2)[2,1])^2,
Qpval=stats::pchisq(Qj,1,lower.tail=FALSE)
)
Qegger2 <- sum(eggeroutliers$Qj)
Qegger2pval <- stats::pchisq(Qegger2, nrow(d)-1, lower.tail=FALSE)
# Collate
re_out <- dplyr::tibble(
id.exposure = id.exposure,
id.outcome = id.outcome,
method = c("RE Egger"),
nsnp = nrow(d),
b = c(egger2$coefficients[2,1]),
se = c(egger2$coefficients[2,2]),
ci_low = b - se * 1.96,
ci_upp = b + se * 1.96,
pval = stats::pt(abs(b / se), nrow(d)-2, lower.tail=FALSE) * 2
)
fe_out <- re_out
fe_out$se <- fe_out$se / max(1, egger2$sigma)
fe_out$pval <- stats::pnorm(abs(fe_out$b / fe_out$se), lower.tail=FALSE) * 2
fe_out$method <- c("FE Egger")
out <- dplyr::bind_rows(fe_out, re_out)
# Pleiotropy
heterogeneity <- dplyr::tibble(
id.exposure = id.exposure,
id.outcome = id.outcome,
method = c("Egger"),
Q = c(Qegger2),
df = c(nrow(d)-2),
pval = stats::pchisq(Q, df, lower.tail=FALSE)
)
directional_pleiotropy <- dplyr::tibble(
id.exposure = id.exposure,
id.outcome = id.outcome,
method = c("FE Egger intercept", "RE Egger intercept"),
nsnp = nrow(d),
b = c(egger2$coefficients[1,1], egger2$coefficients[1,1]),
se = c(egger2$coefficients[1,2] / max(1, egger2$sigma), egger2$coefficients[1,2]),
pval = stats::pt(abs(b/se), nrow(d)-2, lower.tail=FALSE) * 2
)
ret <- list(estimates=out, heterogeneity = heterogeneity, directional_pleiotropy = directional_pleiotropy, outliers=eggeroutliers)
return(ret)
}
mr_mean <- function(dat, parameters=default_parameters())
{
m1 <- try(mr_mean_ivw(dat))
m2 <- try(mr_mean_egger(dat))
if(inherits(m1, "try-error"))
{
return(NULL)
} else {
if(inherits(m2, "try-error"))
{
return(m1)
} else {
out <- list(
estimates = dplyr::bind_rows(m1$estimates, m2$estimates),
heterogeneity = dplyr::bind_rows(m1$heterogeneity, m2$heterogeneity),
directional_pleiotropy = m2$directional_pleiotropy,
outliers = m1$outliers
)
temp <- dplyr::tibble(
id.exposure = dat$id.exposure[1],
id.outcome = dat$id.outcome[1],
method = "Rucker",
Q = out$heterogeneity$Q[1] - out$heterogeneity$Q[2],
df = 1,
pval = stats::pchisq(Q, df, lower.tail=FALSE)
)
out$heterogeneity <- dplyr::bind_rows(out$heterogeneity, temp)
return(out)
}
}
}
mr_all <- function(dat, parameters=default_parameters())
{
m1 <- mr_mean(dat)
if(sum(dat$mr_keep) > 3)
{
m2 <- try(mr_median(dat, parameters=parameters))
m3 <- try(mr_mode(dat, parameters=parameters)[1:3,])
m1$estimates <- dplyr::bind_rows(m1$estimates, m2, m3)
}
m1$info <- c(list(
id.exposure = dat$id.exposure[1], id.outcome = dat$id.outcome[1]),
system_metrics(dat)
) %>% dplyr::as_tibble()
return(m1)
}
mr_wrapper_single <- function(dat, parameters=default_parameters())
{
dat <- steiger_filtering(dat)
m <- list()
snps_retained <- dplyr::tibble(
SNP = dat$SNP,
outlier = FALSE, steiger = FALSE, both = FALSE
)
m[[1]] <- mr_all(dat, parameters=parameters)
if(!is.null(m[[1]]))
{
if("outliers" %in% names(m[[1]]))
{
temp <- subset(dat, ! SNP %in% subset(m[[1]]$outliers, Qpval < 0.05)$SNP)
m[[2]] <- mr_all(temp, parameters=parameters)
snps_retained$outlier[snps_retained$SNP %in% temp$SNP] <- TRUE
} else {
m[[2]] <- m[[1]]
snps_retained$outlier <- TRUE
}
dat_st <- subset(dat, steiger_dir)
snps_retained$steiger[snps_retained$SNP %in% dat_st$SNP] <- TRUE
if(nrow(dat_st) == 0)
{
m[[3]] <- m[[4]] <- list(
estimates=dplyr::tibble(method="Steiger null", nsnp = 0, b=0, se=NA, ci_low=NA, ci_upp=NA, pval=1)
)
} else {
m[[3]] <- mr_all(dat_st, parameters=parameters)
if("outliers" %in% names(m[[3]]))
{
temp <- subset(dat_st, ! SNP %in% subset(m[[3]]$outliers, Qpval < 0.05)$SNP)
m[[4]] <- mr_all(temp, parameters=parameters)
snps_retained$both[snps_retained$SNP %in% temp$SNP] <- TRUE
} else {
m[[4]] <- m[[3]]
snps_retained$both <- TRUE
}
}
}
if(!is.null(m[[1]]))
{
m[[1]] <- lapply(m[[1]], function(x)
{
x$steiger_filtered <- FALSE
x$outlier_filtered <- FALSE
x$id.exposure <- dat$id.exposure[1]
x$id.outcome <- dat$id.outcome[1]
return(x)
})
}
if(!is.null(m[[2]]))
{
m[[2]] <- lapply(m[[2]], function(x)
{
x$steiger_filtered <- FALSE
x$outlier_filtered <- TRUE
x$id.exposure <- dat$id.exposure[1]
x$id.outcome <- dat$id.outcome[1]
return(x)
})
}
if(!is.null(m[[3]]))
{
m[[3]] <- lapply(m[[3]], function(x)
{
x$steiger_filtered <- TRUE
x$outlier_filtered <- FALSE
x$id.exposure <- dat$id.exposure[1]
x$id.outcome <- dat$id.outcome[1]
return(x)
})
}
if(!is.null(m[[4]]))
{
m[[4]] <- lapply(m[[4]], function(x)
{
x$steiger_filtered <- TRUE
x$outlier_filtered <- TRUE
x$id.exposure <- dat$id.exposure[1]
x$id.outcome <- dat$id.outcome[1]
return(x)
})
}
nom <- lapply(m, names) %>% unlist %>% unique %>% as.list
nom <- nom[nom != "outliers"]
o <- lapply(nom, function(i) {
lapply(m, function(y) y[[i]]) %>% dplyr::bind_rows()
})
names(o) <- nom
o$info <- o$info %>% dplyr::mutate(nsnp_removed = dplyr::first(nsnp)-nsnp)
o$snps_retained <- snps_retained
return(o)
}
#' Perform full set of MR analyses
#'
#'
#' @param dat Output from [harmonise_data()].
#' @param parameters Parameters to pass to MR functions. Output from [default_parameters()] used as default.
#'
#' @export
#' @return list
mr_wrapper <- function(dat, parameters=default_parameters())
{
plyr::dlply(dat, c("id.exposure", "id.outcome"), function(x)
{
message("Performing MR analysis of '", x$id.exposure[1], "' on '", x$id.outcome[1], "'")
d <- subset(x, mr_keep)
o <- mr_wrapper_single(d, parameters=parameters)
o
})
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.