Nothing
## ---- echo=FALSE, out.width='60%', fig.cap="Thrombolytic treatment network, from Phillippo et al. (2018)."----
knitr::include_graphics("Thrombo_network.png")
## -----------------------------------------------------------------------------
library(nmathresh)
# library(coda) # Not required - but prints the summary in a nicer format
# Thrombo.post.summary
## -----------------------------------------------------------------------------
dat.raww <- read.delim(system.file("extdata", "Thrombo_data.txt", package = "nmathresh"))
# print first few rows
head(dat.raww)
n <- nrow(dat.raww) # number of studies
## -----------------------------------------------------------------------------
# Log OR for two-arm trials, arm 2 vs. 1
dat.raww$lor.1 <- with(dat.raww, log(r.2 * (n.1 - r.1) / ((n.2 - r.2) * r.1)) )
dat.raww$k.1 <- dat.raww$t.2 # Arm 2 treatment
dat.raww$b.1 <- dat.raww$t.1 # Reference treatment
# Log OR for three-arm trials, arm 3 vs. 1
dat.raww$lor.2 <- with(dat.raww, log(r.3 * (n.1 - r.1) / ((n.3 - r.3) * r.1)) )
dat.raww$k.2 <- dat.raww$t.3 # Arm 3 treatment (NA if only 2 arms)
dat.raww$b.2 <- ifelse(is.na(dat.raww$k.2), NA, dat.raww$t.1) # Reference treatment
## -----------------------------------------------------------------------------
# LOR variances and covariances, likelihood covariance matrix V
V.diag <- as.list(rep(NA, n))
attach(dat.raww)
for (i in 1:n){
if (dat.raww$n_arms[i] == 2){
V.diag[[i]] <- 1/r.1[i] + 1/r.2[i] + 1/(n.1[i]-r.1[i]) + 1/(n.2[i]-r.2[i])
}
else if (dat.raww$n_arms[i] == 3){
v1 <- 1/r.1[i] + 1/r.2[i] + 1/(n.1[i]-r.1[i]) + 1/(n.2[i]-r.2[i])
v2 <- 1/r.1[i] + 1/r.3[i] + 1/(n.1[i]-r.1[i]) + 1/(n.3[i]-r.3[i])
# Covariance term
c1 <- 1/r.1[i] + 1/(n.1[i] - r.1[i])
V.diag[[i]] <- matrix(c(v1, c1, c1, v2), nrow = 2)
}
}
detach(dat.raww)
library(Matrix)
V <- bdiag(V.diag)
## -----------------------------------------------------------------------------
# Reshape the data to have one row per contrast per study
dat.rawl <- reshape(dat.raww, varying = c("lor.1", "b.1", "k.1", "lor.2", "b.2", "k.2"),
timevar = "c", idvar = "studyID", direction = "long")
# Sort data by study and contrast, removing NA rows
dat.rawl <- dat.rawl[order(dat.rawl$studyID, dat.rawl$c, dat.rawl$b, na.last = NA), ]
N <- nrow(dat.rawl) # number of data points
K <- length(unique(c(dat.rawl$b, dat.rawl$k))) # Number of treatments
## -----------------------------------------------------------------------------
# Construct the design matrix, with a row for each contrast and K-1 columns (parameters)
X <- matrix(0, nrow = N, ncol = K-1)
for (i in 1:N){
X[i, dat.rawl$k[i]-1] <- 1
if (dat.rawl$b[i] != 1){
X[i, dat.rawl$b[i]-1] <- -1
}
}
## -----------------------------------------------------------------------------
# Now we can perform thresholding at the study level
thresh <- nma_thresh(mean.dk = Thrombo.post.summary$statistics[1:(K-1), "Mean"],
lhood = V,
post = Thrombo.post.cov,
nmatype = "fixed",
X = X,
opt.max = FALSE)
## -----------------------------------------------------------------------------
thresh
## ---- fig.width=13, fig.height=5.5, out.width='100%', dpi=300-----------------
# Display using a forest plot, along with 95% confidence intervals for LORs
# Create row labels
dat.rawl$lab <- rep(NA, nrow(dat.rawl))
for (i in 1:nrow(dat.rawl)) {
dat.rawl$lab[i] <- paste0(dat.rawl$studyID[i], " (", dat.rawl$k[i], " vs. ", dat.rawl$b[i], ")")
}
# Calculate 95% CIs
dat.rawl$CI2.5 <- dat.rawl$lor + qnorm(.025)*sqrt(diag(V))
dat.rawl$CI97.5 <- dat.rawl$lor + qnorm(.975)*sqrt(diag(V))
# Calculate the proportion of CI covered by invariant interval, for sorting.
# Coverage <1 means that the CI extends beyond the bias invariant threshold, and
# the threshold is below the level of statistical uncertainty.
dat.rawl$coverage <- apply(cbind(thresh$thresholds$lo / (dat.rawl$CI2.5 - dat.rawl$lor),
thresh$thresholds$hi / (dat.rawl$CI97.5 - dat.rawl$lor)),
1, min, na.rm = TRUE)
# Plot
thresh_forest(thresh,
y = lor, CI.lo = CI2.5, CI.hi = CI97.5,
label = lab, orderby = coverage, data = dat.rawl,
CI.title = "95% Confidence Interval", y.title = "Log OR",
label.title = "Study (Contrast)", xlab = "Log Odds Ratio",
xlim = c(-3, 2), refline = 0, digits = 2,
calcdim = FALSE)
## ---- fig.width=6, fig.height=6, out.width='60%', dpi=300---------------------
thresh_2d(thresh, 1, 2,
xlab = "Adjustment in Study 1 LOR: 3 vs. 1",
ylab = "Adjustment in Study 1 LOR: 4 vs. 1",
xlim = c(-1.5, 0.5), ylim = c(-2, 14),
ybreaks = seq(-2, 14, 2))
## ---- include=FALSE-----------------------------------------------------------
# Reset environment
rm(list = ls())
## -----------------------------------------------------------------------------
K <- 6 # Number of treatments
# Contrast design matrix is
X <- matrix(ncol = K-1, byrow = TRUE,
c(1, 0, 0, 0, 0,
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
0, -1, 1, 0, 0,
0, -1, 0, 1, 0,
0, -1, 0, 0, 1))
# Reconstruct using NNLS
lik.cov <- recon_vcov(Thrombo.post.cov, prior.prec = .0001, X = X)
## -----------------------------------------------------------------------------
thresh <- nma_thresh(mean.dk = Thrombo.post.summary$statistics[1:(K-1), "Mean"],
lhood = lik.cov,
post = Thrombo.post.cov,
nmatype = "fixed",
X = X,
opt.max = FALSE)
## ---- fig.width = 12, fig.height = 3.5, out.width = '100%', dpi = 300---------
# Get treatment codes for the contrasts with data
d.a <- d.b <- vector(length = nrow(X))
for (i in 1:nrow(X)){
d.a[i] <- ifelse(any(X[i, ] == -1), which(X[i, ] == -1), 0) + 1
d.b[i] <- ifelse(any(X[i, ] == 1), which(X[i, ] == 1), 0) + 1
}
# Transform from d_ab style contrast references into d[i] style from the full set of contrasts
# for easy indexing in R
d.i <- d_ab2i(d.a, d.b, K = 6)
# Create plot data
plotdat <- data.frame(lab = paste0(d.b, " vs. ", d.a),
contr.mean = Thrombo.post.summary$statistics[d.i, "Mean"],
CI2.5 = Thrombo.post.summary$quantiles[d.i, "2.5%"],
CI97.5 = Thrombo.post.summary$quantiles[d.i, "97.5%"])
# Plot
thresh_forest(thresh, contr.mean, CI2.5, CI97.5, label = lab, data = plotdat,
label.title = "Contrast", xlab = "Log Odds Ratio", CI.title = "95% Credible Interval",
xlim = c(-.3, .3), refline = 0, digits = 2, calcdim = FALSE)
## ---- include=FALSE-----------------------------------------------------------
# Reset environment
rm(list=ls())
## ---- echo=FALSE, out.width='60%', fig.cap="Social anxiety treatment network, from Phillippo et al. (2018)."----
knitr::include_graphics("Social_Anxiety_network.png")
## ---- eval=FALSE--------------------------------------------------------------
# library(nmathresh)
# library(Matrix)
#
# # library(coda) # Not required - but prints the summary in a nicer format
# # SocAnx.post.summary
## -----------------------------------------------------------------------------
# Read study data
dat.raww <- read.delim(system.file("extdata", "SocAnx_data.txt", package = "nmathresh"))
# Print first few rows
head(dat.raww)
n <- nrow(dat.raww) # Number of studies
# Turn wide study data into long with one row for each arm
dat.rawl <- reshape(dat.raww, varying=c("t.2","y.2","Var.2","t.3","y.3","Var.3",
"t.4","y.4","Var.4","t.5","y.5","Var.5"),
timevar="arm", idvar="studyID", direction="long")
# Sort data by study and contrast, removing NA rows
dat.rawl <- dat.rawl[order(dat.rawl$studyID, dat.rawl$arm, dat.rawl$y, na.last=NA),]
K <- length(unique(c(dat.rawl$t.1, dat.rawl$t))) # Number of treatments
N <- nrow(dat.rawl) # Number of data points
## -----------------------------------------------------------------------------
# Get indices of d, sd, diff in the CODA data
vnames <- sub("(.*)\\[.*","\\1", rownames(SocAnx.post.summary$statistics))
ind.d <- which(vnames=="d")
ind.sd <- which(vnames=="sd")
ind.diff <- which(vnames=="diff")
ind.delta <- which(vnames=="delta")
## -----------------------------------------------------------------------------
# Create likelihood covariance matrix
V.diag <- as.list(rep(NA,n))
attach(dat.raww)
for (i in 1:n){
if (n.arms[i] == 2){
V.diag[[i]] <- Var.2[i]
}
else {
V.diag[[i]] <- matrix(V[i], nrow=n.arms[i]-1, ncol=n.arms[i]-1)
tempVar <- c(Var.2[i], Var.3[i], Var.4[i], Var.5[i])
diag(V.diag[[i]]) <- tempVar[!is.na(tempVar)]
}
}
detach(dat.raww)
lik.cov <- bdiag(V.diag)
## -----------------------------------------------------------------------------
thresh <- nma_thresh(mean.dk = SocAnx.post.summary$statistics[ind.d, "Mean"],
lhood = lik.cov,
post = SocAnx.post.cov,
nmatype = "random",
opt.max = FALSE)
## ---- fig.width=14, fig.height=9.5, out.width='100%', dpi=300-----------------
# 95% CIs
dat.rawl$CI2.5 <- with(dat.rawl, y + qnorm(0.025)*sqrt(Var))
dat.rawl$CI97.5 <- with(dat.rawl, y + qnorm(0.975)*sqrt(Var))
# Study labels
dat.rawl$lab <- with(dat.rawl, paste0(studyID," (",t," vs ",t.1,")"))
# Forest plot - all contrasts, very large
# thresh_forest(thresh, y, CI2.5, CI97.5, label = lab, data = dat.rawl,
# label.title = "Study (Contrast)", xlab = "Standardised Mean Difference",
# xlim = c(-4, 3), y.title = "SMD", refline = 0, digits = 2)
# Forest plot - only contrasts with thresholds <2 SMD
cutoff <- 2
absmin <- function(x) min(abs(x))
dat.rawl$coverage <- apply(thresh$thresholds[, c("lo", "hi")] /
(dat.rawl[, c("CI2.5", "CI97.5")] - dat.rawl$y),
1, absmin)
dat.rawl$ord <- ifelse(thresh$thresholds$lo > -cutoff | thresh$thresholds$hi < cutoff,
dat.rawl$coverage, NA)
thresh_forest(thresh, y, CI2.5, CI97.5, label = lab,
orderby = list(ord, na.last = NA), data = dat.rawl,
label.title = "Study (Contrast)", xlab = "Standardised Mean Difference",
xlim = c(-4, 3), y.title = "SMD", refline = 0, digits = 2, calcdim = FALSE)
## ---- include = FALSE---------------------------------------------------------
# Reset environment
rm(list=ls())
## -----------------------------------------------------------------------------
trt.dat <- read.delim(system.file("extdata", "SocAnx_data.txt", package = "nmathresh"))[, 1:6]
head(trt.dat) # Print first few rows
K <- with(trt.dat, length(unique(c(t.1, t.2, t.3, t.4, t.5)))) -1 # Number of treatments , -1 for NA
# work out which contrasts have data
contr.ab <- data.frame(a = c(), b = c())
for (i in 1:nrow(trt.dat)) {
rowi <- trt.dat[i, which(!is.na(trt.dat[i, 2:6]))+1] # non NA elements of ith row
# get contrast from all combinations of treatments
trtcomb <- combn(rowi, 2, function(x) sapply(x, as.numeric))
a <- apply(trtcomb, 2, min)
b <- apply(trtcomb, 2, max)
# remove contrasts of treatments against themselves
iseq <- a == b
a <- a[!iseq]
b <- b[!iseq]
if (!all(iseq)) contr.ab <- rbind(contr.ab, cbind(a, b))
}
contr.ab <- unique(contr.ab[order(contr.ab$a, contr.ab$b), ])
# Contrast design matrix
X <- matrix(0, nrow = nrow(contr.ab), ncol = K-1)
for (i in 1:nrow(X)) {
if (contr.ab[i, "a"] > 1) X[i, contr.ab[i, "a"] - 1] <- -1
if (contr.ab[i, "b"] > 1) X[i, contr.ab[i, "b"] - 1] <- 1
}
## -----------------------------------------------------------------------------
# Get indices of d, sd, diff in the CODA data
vnames <- sub("(.*)\\[.*","\\1", rownames(SocAnx.post.summary$statistics))
ind.d <- which(vnames=="d")
ind.sd <- which(vnames=="sd")
ind.diff <- which(vnames=="diff")
ind.delta <- which(vnames=="delta")
## -----------------------------------------------------------------------------
# Class model is used, so use the prior mean precision from the gamma distribution
prior.prec <- rep(3.9/0.35, 40)
# Other than for treatment 3
prior.prec[2] <- 0.0001
lik.cov <- recon_vcov(SocAnx.post.cov[1:(K-1), 1:(K-1)], prior.vcov = diag(1/prior.prec), X = X)
## -----------------------------------------------------------------------------
thresh <- nma_thresh(mean.dk = SocAnx.post.summary$statistics[ind.d, "Mean"],
lhood = lik.cov,
post = SocAnx.post.cov[1:(K-1), 1:(K-1)],
nmatype = "fixed",
X = X,
opt.max = FALSE)
## ---- fig.width=13, fig.height=11, out.width='100%', dpi=300------------------
# Get indices of contrasts in likelihood
d.a <- d.b <- vector(length = nrow(X))
for (i in 1:nrow(X)) {
d.a[i] <- ifelse(any(X[i, ] == -1), which(X[i, ] == -1), 0) + 1
d.b[i] <- ifelse(any(X[i, ] == 1), which(X[i, ] == 1), 0) + 1
}
d.i <- d_ab2i(d.a, d.b, K = K)
# Contrast labels and credible intervals (from the posterior summary)
plotdat <- data.frame(
contr = paste0(d.b, " vs. ", d.a),
contr.mean = SocAnx.post.summary$statistics[ind.diff[d.i], "Mean"],
CI2.5 = SocAnx.post.summary$quantiles[ind.diff[d.i], "2.5%"],
CI97.5 = SocAnx.post.summary$quantiles[ind.diff[d.i], "97.5%"]
)
cutoff <- 2
absmin <- function(x) min(abs(x))
plotdat$ord <- ifelse(thresh$thresholds$lo > -cutoff | thresh$thresholds$hi < cutoff,
apply(thresh$thresholds[, c("lo", "hi")], 1, absmin), NA)
thresh_forest(thresh, contr.mean, CI2.5, CI97.5,
label = contr, orderby = list(ord, na.last = NA), data = plotdat,
label.title = "Contrast", xlab = "SMD", xlim = c(-4, 3),
CI.title = "95% Credible Interval",
refline = 0, digits = 2, calcdim = FALSE)
## -----------------------------------------------------------------------------
# Drug treatments (+ combi therapies)
drugtrts <- c(9:23, 37:41)
# Which data points compare these to an inactive trt?
drugdats <- which(contr.ab$a %in% 1:3 & contr.ab$b %in% drugtrts)
# Get U solutions by summing the indivual solutions of drug data points
U.drugs <- 1 / (rowSums(1 / thresh$Ukstar[,drugdats]))
# Which contrasts do the rows of Ukstar correspond to?
Ukstar.ab <- d_i2ab(1:(K*(K-1)/2), K)
Ukstar.ab <- Ukstar.ab[Ukstar.ab$a == thresh$kstar | Ukstar.ab$b == thresh$kstar, ]
## -----------------------------------------------------------------------------
# Thresholds are then
thresh.drugs <- get.int(U.drugs, thresh$kstar, 1:K, Ukstar.ab)
## ---- fig.height=6, fig.width=8, out.width='80%', dpi=300---------------------
## Function to plot the common invariant interval with the data
plotII <- function(thresh, contr.mean, CrI.lo, CrI.hi, rowlabs, xlim, xlab, ylab, ...){
yaxs <- length(contr.mean):1
# split plot in two
layout(matrix(1:2,nrow=1), widths=c(.2,1))
# plot row labels on left side
gp <- par(mar=c(5,4,1,0))
plot(rep(0,length(yaxs)), yaxs, pch=NA, ylim=c(.5,yaxs[1]+.5), ylab="",
xlab="", yaxt="n", xaxt="n", bty="n")
text(0, yaxs, labels=rowlabs,xpd=NA)
title(ylab=ylab, line=2)
# fake plot for setup of right side
par(mar=c(5,1,1,2))
plot(contr.mean, yaxs, pch=NA, yaxt="n", xlim=xlim,
ylim=c(.5,yaxs[1]+.5), ylab="", xlab="",...)
title(xlab=xlab, line=2)
# reference line
abline(v=0, lty=2, col="gray")
# combined invariant region
polygon(rep(c(contr.mean + thresh$lo, rev(contr.mean) + thresh$hi), each=2),
c(rep(yaxs,each=2) + c(.5,-.5), rep(rev(yaxs),each=2) + c(-.5,.5)),
col=rgb(.7,.8,.9,.7),
border=rgb(.6,.7,.8))
# credible intervals
segments(y0=yaxs, x0=CrI.lo, x1=CrI.hi, lend=1)
# contrast means
points(contr.mean, yaxs, pch=21, col="black", bg="white")
# write new optimal treatments at either side
text(xlim[1], round(length(yaxs)/2),
labels=as.expression(substitute(tilde(k)*"* = "*xx,list(xx=thresh$lo.newkstar))),
pos=4)
text(xlim[2], round(length(yaxs)/2),
labels=as.expression(substitute(tilde(k)*"* = "*xx,list(xx=thresh$hi.newkstar))),
pos=2)
# write invariant interval below plot
with(thresh, title(xlab=paste0("Invariant interval about zero: ",lo.newkstar,
" (",formatC(lo,digits=2,format="f"),", ",
formatC(hi,digits=2,format="f"),") ",
hi.newkstar), line=3))
par(gp)
}
plotII(thresh.drugs,
SocAnx.post.summary$statistics[ind.diff[drugdats], "Mean"],
SocAnx.post.summary$quantiles[ind.diff[drugdats], "2.5%"],
SocAnx.post.summary$quantiles[ind.diff[drugdats], "97.5%"],
rowlabs = paste0(contr.ab[drugdats, "b"], " vs. ", contr.ab[drugdats, "a"]),
xlim = c(-4, 1.5), ylab = "Drug vs. Inactive Contrasts", xlab = "SMD")
## ---- fig.width=8, fig.height=5.5, out.width='80%', dpi=300-------------------
# Psych treatments
psychtrts <- c(4:8, 24:36)
# Which data points compare these to an inactive trt?
psychdats <- which(contr.ab$a %in% 1:3 & contr.ab$b %in% psychtrts)
# Get U solutions by summing the influences of drug data points
U.psych <- 1 / (rowSums(1 / thresh$Ukstar[,psychdats]))
# Thresholds are then
thresh.psych <- get.int(U.psych, thresh$kstar, 1:K, Ukstar.ab)
plotII(thresh.psych,
SocAnx.post.summary$statistics[ind.diff[psychdats], "Mean"],
SocAnx.post.summary$quantiles[ind.diff[psychdats], "2.5%"],
SocAnx.post.summary$quantiles[ind.diff[psychdats], "97.5%"],
rowlabs=paste0(contr.ab[psychdats,"b"]," vs. ",contr.ab[psychdats,"a"]),
xlim=c(-3,2), ylab="Psych vs. Inactive Contrasts", xlab="SMD")
## ---- fig.width=8, fig.height=8, out.width='80%', dpi=300---------------------
thresh.drugpsych <- list(
Ukstar = cbind(U.drugs, U.psych),
kstar = thresh$kstar
)
thresh_2d(thresh.drugpsych, 1, 2,
xlab = "SMD adjustment: Drug vs. Inactive",
ylab = "SMD adjustment: Psych vs. Inactive",
xlim = c(-6, 2), ylim = c(-6, 2),
breaks = -6:2)
## ---- eval=FALSE--------------------------------------------------------------
# # Use coda package to read in the CODA files generated by WinBUGS
# # The CODA files need only contain the dd parameter (contrasts).
# library(coda)
# dat.CODA <- mcmc.list(lapply(c("Coda1.txt",
# "Coda2.txt",
# "Coda3.txt"),
# read.coda, index.file = "CodaIndex.txt"))
#
#
# # Posterior summary table
# Thrombo.post.summary <- summary(dat.CODA)
#
# # Posterior covariance matrix of basic treatment effects d_k = d_1k
# Thrombo.post.cov <- cov(as.matrix(dat.CODA[,1:5]))
## ---- eval=FALSE--------------------------------------------------------------
# # Use coda package to read in the CODA files generated by WinBUGS
# # The CODA files need only contain the d, delta, and sd parameters.
# library(coda)
# dat.CODA <- mcmc.list(lapply(c("Coda1.txt",
# "Coda2.txt"),
# read.coda, index.file = "CodaIndex.txt"))
#
# # Get indices of parameters
# vnames <- sub("(.*)\\[.*","\\1", varnames(dat.CODA))
# ind.d <- which(vnames=="d")
# ind.diff <- which(vnames=="diff")
# ind.delta <- which(vnames=="delta")
# ind.sd <- which(vnames=="sd")
#
# # Posterior summary table
# SocAnx.post.summary <- summary(dat.CODA)
#
# # Posterior covariance matrix of d and delta parameters
# SocAnx.post.cov <- cov(as.matrix(dat.CODA[,c(ind.d, ind.delta)]))
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.