Meta Tutorial
Meta Tutorial
This vignette provides up-to-date commands for the analyses in “How to perform a meta-analysis with R: a
practical tutorial”, Evid Based Ment Health (Balduzzi, Rücker, and Schwarzer 2019).
Install R packages
install.packages(c("meta", "metasens"))
library(metasens)
Note, a similar message would be printed for R package metasens. However, this vignette does not actually
load metasens as it might not be installed in addition to meta.
Note, in the publication, argument ‘method.tau’ was used in R function metabin(). Here, we set the
Paule-Mandel method as the default for any meta-analysis conducted in the current R session.
1
str(joy)
#> 'data.frame': 17 obs. of 9 variables:
#> $ author: chr "Arvanitis" "Beasley" "Bechelli" "Borison" ...
#> $ year : int 1997 1996 1983 1992 1993 1964 1962 1974 1994 1982 ...
#> $ resp.h: int 25 29 12 3 10 11 7 8 19 1 ...
#> $ fail.h: int 25 18 17 9 11 8 18 9 45 9 ...
#> $ drop.h: int 2 22 1 0 0 0 1 0 2 0 ...
#> $ resp.p: int 18 20 2 0 3 1 4 3 14 0 ...
#> $ fail.p: int 33 14 28 12 19 14 21 10 50 10 ...
#> $ drop.p: int 0 34 1 0 0 0 1 0 2 0 ...
#> $ miss : chr "With missing data" "With missing data" "With missing data" "Without missing data" ..
2
#> Test of heterogeneity:
#> Q d.f. p-value
#> 27.24 16 0.0388
#>
#> Details on meta-analytical method:
#> - Mantel-Haenszel method (common effect model)
#> - Inverse variance method (random effects model)
#> - Paule-Mandel estimator for tauˆ2
#> - Q-Profile method for confidence interval of tauˆ2 and tau
#> - Continuity correction of 0.5 in studies with zero cell frequencies
3
#>
#> Quantifying heterogeneity:
#> tauˆ2 = 0.1754 [0.0000; 1.0088]; tau = 0.4188 [0.0000; 1.0044]
#> Iˆ2 = 41.3% [0.0%; 67.0%]; H = 1.30 [1.00; 1.74]
#>
#> Test of heterogeneity:
#> Q d.f. p-value
#> 27.24 16 0.0388
#>
#> Results for subgroups (common effect model):
#> k RR 95%-CI Q Iˆ2
#> With missing data 10 1.70 [1.35; 2.14] 13.73 34.4%
#> Without missing data 7 4.36 [2.45; 7.77] 3.35 0.0%
#>
#> Test for subgroup differences (common effect model):
#> Q d.f. p-value
#> Between groups 8.82 1 0.0030
#>
#> Results for subgroups (random effects model):
#> k RR 95%-CI tauˆ2 tau
#> With missing data 10 1.71 [1.13; 2.59] 0.1785 0.4224
#> Without missing data 7 3.80 [2.13; 6.80] 0 0
#>
#> Test for subgroup differences (random effects model):
#> Q d.f. p-value
#> Between groups 4.80 1 0.0285
#>
#> Details on meta-analytical method:
#> - Mantel-Haenszel method (common effect model)
#> - Inverse variance method (random effects model)
#> - Paule-Mandel estimator for tauˆ2
#> - Q-Profile method for confidence interval of tauˆ2 and tau
#> - Continuity correction of 0.5 in studies with zero cell frequencies
4
Haloperidol Placebo Weight Weight
Study Events Total Events Total Risk Ratio RR 95%−CI (common) (random)
5
meths = c("Available case analysis (ACA)",
"Impute no events (ICA-0)", "Impute events (ICA-1)",
"Observed risk in control group (ICA-pc)",
"Observed risk in experimental group (ICA-pe)",
"Observed group-specific risks (ICA-p)",
"Best-case scenario (ICA-b)", "Worst-case scenario (ICA-w)",
"Gamble-Hollis analysis",
"IMOR.e = 2, IMOR.c = 2", "IMOR.e = 0.5, IMOR.c = 0.5")
# Use inverse-variance method for pooling (which is used for
# imputation methods)
m.publ.iv = update(m.publ, method = "Inverse")
# Combine results (random effects)
mbr = metabind(m.publ.iv,
mmiss.0, mmiss.1,
mmiss.pc, mmiss.pe, mmiss.p,
mmiss.b, mmiss.w, mmiss.gh,
mmiss.imor2, mmiss.imor0.5,
name = meths, pooled = "random")
Available case analysis (ACA) 0.4127 0.18 27.24 0.04 2.15 [1.51; 3.06]
Impute no events (ICA−0) 0.2511 0.09 21.36 0.16 2.22 [1.63; 3.04]
Impute events (ICA−1) 0.6006 0.23 40.06 0.00 1.99 [1.39; 2.84]
Observed risk in control group (ICA−pc) 0.4149 0.18 27.34 0.04 2.11 [1.47; 3.02]
Observed risk in experimental group (ICA−pe) 0.4623 0.18 29.76 0.02 1.99 [1.40; 2.83]
Observed group−specific risks (ICA−p) 0.4081 0.17 27.03 0.04 2.13 [1.50; 3.03]
Best−case scenario (ICA−b) 0.2541 0.06 21.45 0.16 2.64 [1.98; 3.51]
Worst−case scenario (ICA−w) 0.7412 0.43 61.83 0.00 1.90 [1.22; 2.94]
Gamble−Hollis analysis 0.1649 0.07 19.16 0.26 2.25 [1.59; 3.18]
IMOR.e = 2, IMOR.c = 2 0.4768 0.20 30.58 0.02 2.11 [1.47; 3.03]
IMOR.e = 0.5, IMOR.c = 0.5 0.3444 0.14 24.40 0.08 2.16 [1.54; 3.03]
0.5 1 2 4
Favours placebo Favours haloperidol
6
Section ‘Assessing and accounting for small-study effects’
Funnel plot
funnel(m.publ)
Trim-and-fill method
tf.publ = trimfill(m.publ)
tf.publ
#> Number of studies: k = 26 (with 9 added studies)
#> Number of observations: o = 1174 (o.e = 645, o.c = 529)
#> Number of events: e = 374
#>
#> RR 95%-CI z p-value
#> Random effects model 1.40 [0.83; 2.38] 1.26 0.2063
#>
#> Quantifying heterogeneity:
#> tauˆ2 = 1.0983 [0.2929; 3.1894]; tau = 1.0480 [0.5412; 1.7859]
#> Iˆ2 = 56.2% [32.1%; 71.8%]; H = 1.51 [1.21; 1.88]
#>
#> Test of heterogeneity:
#> Q d.f. p-value
#> 57.13 25 0.0003
#>
#> Details on meta-analytical method:
#> - Inverse variance method
#> - Paule-Mandel estimator for tauˆ2
#> - Q-Profile method for confidence interval of tauˆ2 and tau
#> - Trim-and-fill method to adjust for funnel plot asymmetry (L-estimator)
summary(tf.publ)
#> RR 95%-CI %W(random)
#> Arvanitis (1997) 1.42 [0.89; 2.25] 6.2
#> Beasley (1996) 1.05 [0.73; 1.50] 6.4
#> Bechelli (1983) 6.21 [1.52; 25.35] 4.5
#> Borison (1992) 7.00 [0.40; 121.94] 2.2
#> Chouinard (1993) 3.49 [1.11; 10.95] 5.0
#> Durost (1964) 8.68 [1.26; 59.95] 3.5
#> Garry (1962) 1.75 [0.58; 5.24] 5.1
7
#> Howard (1974) 2.04 [0.67; 6.21] 5.1
#> Marder (1994) 1.36 [0.75; 2.47] 6.0
#> Nishikawa (1982) 3.00 [0.14; 65.55] 2.0
#> Nishikawa (1984) 9.00 [0.57; 142.29] 2.3
#> Reschke (1974) 3.79 [1.06; 13.60] 4.7
#> Selman (1976) 1.48 [0.94; 2.35] 6.2
#> Serafetinides (1972) 8.38 [0.50; 141.44] 2.3
#> Simpson (1967) 2.27 [0.12; 41.77] 2.2
#> Spencer (1992) 11.00 [1.67; 72.40] 3.6
#> Vichaiya (1971) 19.00 [1.16; 311.71] 2.3
#> Filled: Chouinard (1993) 0.50 [0.16; 1.55] 5.0
#> Filled: Reschke (1974) 0.46 [0.13; 1.64] 4.7
#> Filled: Bechelli (1983) 0.28 [0.07; 1.14] 4.5
#> Filled: Borison (1992) 0.25 [0.01; 4.31] 2.2
#> Filled: Serafetinides (1972) 0.21 [0.01; 3.49] 2.3
#> Filled: Durost (1964) 0.20 [0.03; 1.38] 3.5
#> Filled: Nishikawa (1984) 0.19 [0.01; 3.04] 2.3
#> Filled: Spencer (1992) 0.16 [0.02; 1.04] 3.6
#> Filled: Vichaiya (1971) 0.09 [0.01; 1.49] 2.3
#>
#> Number of studies: k = 26 (with 9 added studies)
#> Number of observations: o = 1174 (o.e = 645, o.c = 529)
#> Number of events: e = 374
#>
#> RR 95%-CI z p-value
#> Random effects model 1.40 [0.83; 2.38] 1.26 0.2063
#>
#> Quantifying heterogeneity:
#> tauˆ2 = 1.0983 [0.2929; 3.1894]; tau = 1.0480 [0.5412; 1.7859]
#> Iˆ2 = 56.2% [32.1%; 71.8%]; H = 1.51 [1.21; 1.88]
#>
#> Test of heterogeneity:
#> Q d.f. p-value
#> 57.13 25 0.0003
#>
#> Details on meta-analytical method:
#> - Inverse variance method
#> - Paule-Mandel estimator for tauˆ2
#> - Q-Profile method for confidence interval of tauˆ2 and tau
#> - Trim-and-fill method to adjust for funnel plot asymmetry (L-estimator)
funnel(tf.publ)
Limit meta-analysis
l1.publ = limitmeta(m.publ)
Note, the printout for the limit meta-analysis is not shown in this vignette as the installation of R package
metasens is optional.
l1.publ
8
pdf("figure5.pdf", width = 10, height = 10)
#
par(mfrow = c(2, 2), pty = "s",
oma = c(0, 0, 0, 0), mar = c(4.1, 3.1, 2.1, 1.1))
#
funnel(m.publ, xlim = c(0.05, 50), axes = FALSE)
axis(1, at = c(0.1, 0.2, 0.5, 1, 2, 5, 10, 50))
axis(2, at = c(0, 0.5, 1, 1.5))
box()
title(main = "Panel A: Funnel plot", adj = 0)
#
funnel(m.publ, xlim = c(0.05, 50), axes = FALSE,
contour.levels = c(0.9, 0.95, 0.99),
col.contour = c("darkgray", "gray", "lightgray"))
legend("topright",
c("p < 1%", "1% < p < 5%", "5% < p < 10%", "p > 10%"),
fill = c("lightgray", "gray", "darkgray", "white"),
border = "white", bg = "white")
axis(1, at = c(0.1, 0.2, 0.5, 1, 2, 5, 10, 50))
axis(2, at = c(0, 0.5, 1, 1.5))
box()
title(main = "Panel B: Contour-enhanced funnel plot", adj = 0)
#
funnel(tf.publ, xlim = c(0.05, 50), axes = FALSE)
axis(1, at = c(0.1, 0.2, 0.5, 1, 2, 5, 10, 50))
axis(2, at = c(0, 0.5, 1, 1.5))
box()
title(main = "Panel C: Trim-and-fill method", adj = 0)
#
funnel(l1.publ, xlim = c(0.05, 50), axes = FALSE,
col.line = 8, lwd.line = 3)
axis(1, at = c(0.1, 0.2, 0.5, 1, 2, 5, 10, 50))
axis(2, at = c(0, 0.5, 1, 1.5))
box()
title(main = "Panel D: Limit meta-analysis", adj = 0)
#
dev.off()
9
Panel A: Funnel plot Panel B: Contour−enhanced funnel plot
0.0
0.0
p < 1%
1% < p < 5%
5% < p < 10%
p > 10%
0.5
0.5
Standard Error
Standard Error
1.0
1.0
1.5
1.5
0.1 0.2 0.5 1.0 2.0 5.0 10.0 50.0 0.1 0.2 0.5 1.0 2.0 5.0 10.0 50.0
0.0
0.5
0.5
Standard Error
Standard Error
1.0
1.0
1.5
1.5
0.1 0.2 0.5 1.0 2.0 5.0 10.0 50.0 0.1 0.2 0.5 1.0 2.0 5.0 10.0 50.0
References
Balduzzi, Sara, Gerta Rücker, and Guido Schwarzer. 2019. “How to Perform a Meta-Analysis with R: A
Practical Tutorial.” Evidence-Based Mental Health 22 (4): 153–60. doi:10.1136/ebmental-2019-300117.
10