A detailed, though not necessarily exhaustive, summary of software available for fitting one-stage IPD meta-analysis models is given in Table 6.2 of our book. These are generic packages for fitting GLMMs, rather than IPD meta-analysis models per se, and require careful implementation to avoid modelling mistakes and estimation issues. Here, we provide some examples.
In Box 6.1 of our book, we applied a one-stage analysis of 10 randomised trials examining the effect of anti-hypertensive treatment on systolic blood pressure (SBP). We allowed for a random treatment effect, and stratified by trial the intercept, residual variances and prognostic effect of baseline SBP. The code to do this in Stata is as follows:
xtmixed sbpl sbpi_trial* trial* treat , nocons || trialid: treat, nocons reml var residuals(ind, by(trialid))
Here, the IPD dataset contains a row for each patient in 10 trials, with column variables for final SBP (sbpl), baseline SBP (sbpi), and trial identification (trialid), and a dummy variable for each trial (trial1, trial2, trial3, etc - e.g. where trial1 = 1 if in trial 1 and 0 otherwise), and the interaction between baseline SBP and trial (sbpi_trial1, sbpi_trial2, etc - e.g. where sbpi_trial1 = sbpi for those in trial 1 and 0 otherwise). The coding of sbi_trial and trial ensure that a separate term is estimated by study for each of the intercept and the effect of baseline SBP. The residuals(ind, by(trialid)) ensures 10 separate independent residual variances are estimated, one for each trial. We might even extend to allow a separate variance for each group in each trial.
In R, the equivalent code is something like:
ipdresults1 <- lme(sbpl ~ 0 + trialid + SBPi_study1 + SBPi_study2 + SBPi_study3 + SBPi_study4 + SBPi_study5 + SBPi_study6 + SBPi_study7 + SBPi_study8 + SBPi_study9 + SBPi_study10 + treat, random = ~ 0 + treat | trialid, weights = varIdent(form = ~1 | trialid), method = "REML")
Again, this allows ten intercepts, ten effects of baseline SBP, and ten residual variances (the latter using the weights = ... option)
In Box 6.2 of our book, we applied one-stage analyses of 7 randomised trials with a binary outcome. Focusing on the approach that allows a random treatment effect, stratifies the intercepts by study and centers the treatment variable by the proportion treated in the trial (to improve estimation of the between-study variance), the code is:
melogit outcome treat_cent trial*, nocons || trialid: treat_cent, nocons or
As before, trial* is just shorthand for including trial1 to trial7 (dummy variables) to allow 7 intercepts, one per trial. In R, the equivalent code is something like:
ipdresults2 <- glmer(outcome ~ treat_cent + trialid.f + (treat_cent -1 | trialid) -1, family = binomial)
Again, trialid.f denotes a factor variable of trial ID, so that a separate intercept is estimated for each trial.