Skip to content

Instantly share code, notes, and snippets.

@joelkuiper
Last active July 19, 2024 09:25
Show Gist options
  • Save joelkuiper/e910602e6ea39ee2e320 to your computer and use it in GitHub Desktop.
Save joelkuiper/e910602e6ea39ee2e320 to your computer and use it in GitHub Desktop.
Convert contrast based format to data.re format by GeMTC, computing or approximating the baseline se
library(gemtc)
convert <- function(re) {
options(stringsAsFactors = FALSE) # Because R
results <- data.frame()
studies <- unique(re$study)
entry <- function(study, treatment, diff, std.err) {
list(study = study, treatment = treatment, diff = diff, std.err = std.err)
}
as.entry <- function(row) {
entry(row$study, row$treatment, row$diff, row$std.err)
}
for(studyId in studies) {
data <- subset(re, study == studyId)
if(nrow(data) == 1) {
## Two-arm study
base <- entry(studyId, data$base, NA, NA)
treatment <- as.entry(data[1, ])
results <- do.call("rbind", list(results, base, treatment))
} else {
## Multi-arm study
## These entries are similar, but require standard error of the mean for the baseline
## We try to compute this if possible, if not we approximate it
## Guess at most common base, which is the one most referred to
base.table <- table(data$base)
base.trt <- names(base.table)[[which.max(base.table)]]
treatments <- subset(data, base == base.trt)
calc.base.se <- function(d.ab.se, d.ac.se, d.bc.se) {
## Let $Var(D_{BC}) = Var(D_{AB}) + Var(D_{AC}) - 2Var(Y_A)$, thus
## $se_B = \sqrt{(se^2_{AB} + se^2_{CB} - se^2_{AC}) / 2}$
sqrt((d.ab.se^2 + d.ac.se^2 - d.bc.se^2) / 2)
}
approx.active.comparison <- function(d.ab, d.ac) {
## Try to use approximate Var(D_bc) using number of participants, if available (formula 9, Brooks et.al.)
## assuming the standard error is proportional to 1/sqrt(n)
stopifnot(d.ab$base.n == d.ac$base.n) ## A is base should have same number of participants
n.a <- d.ab$base.n
n.b <- d.ab$treatment.n
n.c <- d.ac$treatment.n
if(all(!is.na(c(n.a, n.b, n.c)))) {
sqrt(((d.ab$std.err^2 + d.ac$std.err^2) * (1/n.b + 1/n.c)) / (1/n.b + 1/n.c + 2/n.a))
} else {
NA
}
}
base.se <- function(b, trt1, trt2) {
d.ab <- subset(data, base == b & treatment == trt1)
d.ac <- subset(data, base == b & treatment == trt2)
d.bc <- subset(data, base == trt2 & treatment == trt1)
se <- NA
if(nrow(d.bc) != 0) {
## We have enough data to compute baseline se
se <- calc.base.se(d.ab$std.err, d.ac$std.err, d.bc$std.err)
} else {
## We need to approximate D_bc
d.bc.std.err <- approx.active.comparison(d.ab, d.ac)
if(!is.na(d.bc.std.err)) {
se <- calc.base.se(d.ab$std.err, d.ac$std.err, d.bc.std.err)
}
}
se
}
## Find the combinations of treatments that we could use (e.g. BC, BD)
combinations <- t(combn(as.character(treatments$treatment), 2))
## Try methods by Brooks et.al. to computer or approximate baseline se,
## We take the median of all these values, NAs ommited
se <- median(apply(combinations, 1, function(row) { base.se(base.trt, row[[1]], row[[2]]) }), na.rm=T)
## Append the treatments associated with the base
if(is.finite(se)) { # not NaN, NA or infinite
results <- rbind(results, entry(studyId, base.trt, NA, se))
for(entry in by(treatments, 1:nrow(treatments), as.entry)) {
results <- rbind(results, entry)
}
} else {
warning(paste("could not calculate baseline std.err from data for study", studyId, "omitting"))
}
}
}
options(stringsAsFactors = TRUE) # Because R, but lets not break compatibility
results
}
data.ab <- read.table(textConnection('
study treatment responders sampleSize
01 Salmeterol 1 229
01 Placebo 1 227
02 Fluticasone 4 374
02 Salmeterol 3 372
02 SFC 2 358
02 Placebo 7 361
03 Salmeterol 1 554
03 Placebo 2 270'), header=T)
re <- read.table(textConnection('
study base treatment diff std.err base.n treatment.n
4 Placebo Fluticasone -0.267 0.203 NA NA
5 Placebo SFC -0.209 0.098 1524 1533
5 Placebo Salmeterol -0.154 0.096 1524 1521
5 Placebo Fluticasone 0.055 0.092 1524 1534
5 Salmeterol SFC -0.056 0.100 1521 1533
5 Fluticasone SFC -0.264 0.096 1534 1533
'), header=T)
data.re <- convert(re)
data.re
network <- mtc.network(data.ab=data.ab, data.re=data.re)
model <- mtc.model(network,
link="cloglog",
likelihood="binom",
linearModel="fixed",
hy.prior=mtc.hy.prior("std.dev", "dunif", 0, "om.scale"))
mtc.run(model) -> results
forest(relative.effect(results, t1="Placebo"))
@mintsun0035
Copy link

mintsun0035 commented Jun 17, 2016

i am a chinese student and my english is poor, but your code is every exciting!

What an outstanding contribution! It provides an enlighing look at MTM for survival data. Thank you very much for your time in posting this material.
I am a big fan of your works!
I am also working on a meta-analysis of survival data across several clinical trials and a doctor working in oncology department in Wuhan university , CHINA So, none can help me, as you know.And I ask you for help to analyse the data.
My email is sunmin-0715@163.com. Thanks so much!

@mintsun0035
Copy link

#1

rm(list=ls())
getwd()
setwd("F:/0108gemtc-master_HR混合数据_杠杆图")

F:\0108gemtc-master

install.packages("gemtc")

也可以是如下路径

setwd("F:\0108gemtc-master\gemtc")

setwd("F:\0108gemtc-master\gemtc\tests")

F:\0108gemtc-master_HR混合数据_杠杆图

#2

library(coda)
library(gemtc)
library(lattice)
library(coda)
library(gemtc)
library(R2OpenBUGS)
library(rjags)

data <- read.table(textConnection('

study treatment responders sampleSize

#1 1 3 39
#1 2 3 38
#2 1 14 116
#2 2 7 114
#3 1 11 93
#3 2 5 69
#4 1 127 1520
#4 2 102 1533
#5 1 27 365
#5 2 28 355
#6 1 6 52
#6 2 4 59
#7 1 152 939
#7 2 98 945
#8 1 48 471
#8 2 60 632
#9 1 37 282
#9 2 25 278
#10 1 188 1921
#10 2 138 1916
#11 1 52 583
#11 2 64 873
#12 1 47 266
#12 2 45 263
#13 1 16 293
#13 2 9 291
#14 1 45 883
#14 2 57 858
#15 1 31 147
#15 2 25 154
#16 1 38 213
#16 2 33 207
#17 1 12 122
#17 2 28 251
#18 1 6 154
#18 2 8 151
#19 1 3 134
#19 2 6 174
#20 1 40 218
#20 2 32 209
#21 1 43 364
#21 2 27 391
#22 1 39 674
#22 2 22 680'), header=T)

Binom/logit (blockers)

network <- mtc.network(data.ab = data)

model <- mtc.model(network, linearModel='fixed')

Binom/logit (smoking)

network <- read.mtc.network(system.file('extdata/luades-smoking.gemtc', package='gemtc'))

model <- mtc.model(network, linearModel='fixed')

Relative effect data

network <- mtc.network(data.re=read.table('gemtc/tests/data/parkinson-diff.data.txt', header=TRUE))

model <- mtc.model(network, linearModel='fixed', likelihood='normal', link='identity')

model <- mtc.model(network, linearModel='random', likelihood='normal', link='identity')

Mixed data

network <- mtc.network(data.ab=read.table('./gemtc/tests/data/parkinson-shared.data-ab.txt', header=TRUE),
data.re=read.table('./gemtc/tests/data/parkinson-shared.data-re.txt', header=TRUE))

study treatment mean std.dev sampleSize

#1 A -1.22 0.504 1
#1 C -1.53 0.439 1
#2 A -0.7 0.282 1
#2 B -2.4 0.258 1
#3 A -0.3 0.505 1
#3 B -2.6 0.510 1
#3 D -1.2 0.478 1

study treatment diff std.err

#4 C NA NA
#4 D -0.35 0.441941738
#5 C NA NA
#5 D 0.55 0.555114559
#6 D NA NA
#6 E -0.3 0.274276316
#7 D NA NA
#7 E -0.3 0.320087245

plot(network)

link是怎么处理,log还是别的identity

likelihood似然比是拟合方式是 binorm是 二项式

linemode是固定还是随机

likelihood是 normal正态还是binomial二项式

result.ns <- mtc.nodesplit(network, factor=2.5, n.chain=4, linearModel="random", n.adapt=50, n.iter=500, thin=10, likelihood="binom", link="log")

model <- mtc.model(network, linearModel='fixed', likelihood='normal', link='identity')

model <- mtc.model(network, linearModel='random', likelihood='normal', link='identity')

Poisson/log (dietary fat, 2b)

network <- mtc.network(dget('gemtc/tests/data/fat-survival.data.txt'))

... edit

model <- mtc.model(network, linearModel='fixed', likelihood='poisson', link='log')

result <- mtc.run(model)

summary(result)

默认是和治疗D进行比较

forest(result)

结果如下

Mean SD Naive SE Time-series SE

d.D.A 0.5243 0.4831 0.0017081 0.0057651

d.D.B -1.2863 0.5253 0.0018573 0.0057812

d.D.C 0.0457 0.3227 0.0011409 0.0017617

d.D.E -0.3018 0.2091 0.0007394 0.0007394

#3-----默认值md--孙敏额外加入数据,画图用—————————————————————————————————————————————————————

results <- mtc.run(model, sampler = NA, n.adapt = 5000, n.iter = 20000, thin = 1)
forest(relative.effect(results, "A"))
#4-----默认值md----

forest(relative.effect(results, "B"))
forest(relative.effect(results, "C"))
#5-----默认值md----

summary(relative.effect(results, "B", c("A", "C")))
#6-----默认值md----

相对效应量结果

Creates a forest plot of the relative effects

tbl <- relative.effect.table(results)

Print the n*n table

print(tbl)

Plot effect relative to treatment "C"

forest(tbl, "A")

Write to CSV (e.g. to import to Excel, then use in a Word table)

write.csv(tbl, "smoking-effects.csv")

Note: use write.csv2 for Western European locales

#3-----默认值md----默认值md--孙敏额外加入数据,画图用——————————————————————————————————————————————
#3-----默认值md----默认值md--回到原来的程序——————————————————————————————————————————————

print(result$deviance)

7Below not generalized for multi-arm data 多臂数据不行----

w <- sign(r - rfit) * sqrt(devbar)

plot(w, leverage, xlim=c(-3,3), ylim=c(0, 4.5))

x <- seq(from=-3, to=3, by=0.05)

for (c in 1:4) { lines(x, c - x^2) }

residual deviance plot

if (model$data$ns.r2 + model$data$ns.rm == 0) {
tpl <- gemtc:::arm.index.matrix(model[['network']])
study <- matrix(rep(1:nrow(tpl), times=ncol(tpl)), nrow=nrow(tpl), ncol=ncol(tpl))
study <- t(study)[t(!is.na(tpl))]
devbar <- t(result$deviance$dev.ab)[t(!is.na(tpl))]
title <- "Per-arm residual deviance"
xlab <- "Arm"
} else {
nd <- model$data$na
nd[-(1:model$data$ns.a)] <- nd[-(1:model$data$ns.a)] - 1
devbar <- c(apply(result$deviance$dev.ab, 1, sum, na.rm=TRUE), result$deviance$dev.re) / nd
study <- 1:length(devbar)
title <- "Per-study mean per-datapoint residual deviance"
xlab <- "Study"
}

plot(devbar, ylim=c(0,max(devbar, na.rm=TRUE)),
ylab="Residual deviance", xlab=xlab,
main=title, pch=c(1, 22)[(study%%2)+1])
for (i in 1:length(devbar)) {
lines(c(i, i), c(0, devbar[i]))
}

w <- sign(r - rfit) * sqrt(devbar)

9以下可以作图,多臂数据

plot(w, leverage, xlim=c(-3,3), ylim=c(0, 4.5))

x <- seq(from=-3, to=3, by=0.05)

for (c in 1:4) { lines(x, c - x^2) }

fit.ab <- apply(result$deviance$fit.ab, 1, sum, na.rm=TRUE)
dev.ab <- apply(result$deviance$dev.ab, 1, sum, na.rm=TRUE)
lev.ab <- dev.ab - fit.ab
fit.re <- result$deviance$fit.re
dev.re <- result$deviance$dev.re
lev.re <- dev.re - fit.re
nd <- model$data$na
nd[-(1:model$data$ns.a)] <- nd[-(1:model$data$ns.a)] - 1
w <- sqrt(c(dev.ab, dev.re) / nd)
lev <- c(lev.ab, lev.re) / nd

plot(w, lev, xlim=c(0, max(c(w, 2.5))), ylim=c(0, max(c(lev, 4))),
xlab="Square root of residual deviance", ylab="Leverage",
main="Leverage versus residual deviance")
mtext("Per-study mean per-datapoint contribution")

x <- seq(from=0, to=3, by=0.05)
for (c in 1:4) { lines(x, c - x^2) }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment