Getting started¶
This page takes one dataset from raw 2x2 tables to a pooled estimate, a meta-regression and two plots. Every code block on the page runs as shown.
The data are the BCG vaccine trials of Colditz et al. (1994), https://doi.org/10.1001/jama.1994.03510330076038: for each
trial the number of tuberculosis cases and non-cases among vaccinated (tpos, tneg) and control (cpos, cneg)
subjects, with the absolute latitude of the trial site (ablat).
Conventions¶
- Function and argument names are metafor's, with
.replaced by_.rma.uniisrma_uni, andrmais an alias. - Columns of
dataare given by name ('yi','vi') or as arrays. Moderators are a formula string (mods='~ ablat') or a matrix. - Indices are 0-based in code (
btt=[1]), while printed output counts from 1, as metafor does. - A fitted model is a frozen dataclass.
print(res)gives metafor's summary, and the fields hold the numbers (res.beta,res.se,res.tau2,res.I2). - The functions you call on a fit are the same as in R:
predict,confint,anova,profile,influenceand so on.
Effect sizes¶
escalc turns the raw counts into log risk ratios (yi) and their sampling variances (vi):
from metafopy import datasets, escalc
bcg = datasets.load('dat.bcg')
dat = escalc(measure='RR', ai='tpos', bi='tneg', ci='cpos', di='cneg', data=bcg)
print(dat[['trial', 'author', 'year', 'yi', 'vi']].head())
trial author year yi vi
0 1 Aronson 1948 -0.889311 0.325585
1 2 Ferguson & Simes 1949 -1.585389 0.194581
2 3 Rosenthal et al 1960 -1.348073 0.415368
3 4 Hart & Sutherland 1977 -1.441551 0.020010
4 5 Frimodt-Moller et al 1973 -0.217547 0.051210
A random-effects model¶
from metafopy import rma
res = rma('yi', 'vi', data=dat)
print(res)
Random-Effects Model (k = 13; tau^2 estimator: REML)
tau^2 (estimated amount of total heterogeneity): 0.3132 (SE = 0.1664)
tau (square root of estimated tau^2 value): 0.5597
I^2 (total heterogeneity / total variability): 92.22%
H^2 (total variability / sampling variability): 12.86
Test for Heterogeneity:
Q(df = 12) = 152.2330, p-val < .0001
Model Results:
estimate se zval pval ci.lb ci.ub
-0.7145 0.1798 -3.9744 <.0001 -1.0669 -0.3622 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
The default heterogeneity estimator is REML, as in metafor. Choose another with method, for example
rma('yi', 'vi', data=dat, method='DL'). Pick the tests and intervals with test='knha' (Knapp-Hartung) or level=90.
The numbers are fields of the result:
print(res.beta, res.se, res.tau2, res.I2)
[-0.71453235] [0.17978153] 0.3132433259808949 92.22138607496555
Back-transform and predict¶
The pooled log risk ratio is hard to read. predict takes a transformation:
import numpy
from metafopy import predict
print(predict(res, transf=numpy.exp))
pred ci.lb ci.ub pi.lb pi.ub
0 0.4894 0.3441 0.6962 0.1546 1.549
The columns pi.lb and pi.ub are the prediction interval: where the true effect of a new trial would fall.
Meta-regression¶
Add a moderator with a formula. The effect of the vaccine depends strongly on latitude:
res_lat = rma('yi', 'vi', mods='~ ablat', data=dat)
print(res_lat)
print(predict(res_lat, newmods=[10, 30, 50], transf=numpy.exp))
Mixed-Effects Model (k = 13; tau^2 estimator: REML)
tau^2 (estimated amount of residual heterogeneity): 0.0764 (SE = 0.0591)
tau (square root of estimated tau^2 value): 0.2763
I^2 (residual heterogeneity / unaccounted variability): 68.39%
H^2 (unaccounted variability / sampling variability): 3.16
R^2 (amount of heterogeneity accounted for): 75.62%
Test for Residual Heterogeneity:
QE(df = 11) = 30.7331, p-val = 0.0012
Test of Moderators (coefficient 2):
QM(df = 1) = 16.3571, p-val < .0001
Model Results:
estimate se zval pval ci.lb ci.ub
intrcpt 0.2515 0.2491 1.0095 0.3127 -0.2368 0.7397
ablat -0.0291 0.0072 -4.0444 <.0001 -0.0432 -0.0150 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
pred ci.lb ci.ub pi.lb pi.ub
0 0.9612 0.6668 1.3857 0.5000 1.8478
1 0.5371 0.4355 0.6623 0.3005 0.9600
2 0.3001 0.2144 0.4201 0.1586 0.5678
newmods lists the moderator values to predict at (the intercept is added for you).
Confidence intervals for heterogeneity¶
from metafopy import confint
print(confint(res))
estimate ci.lb ci.ub
tau^2 0.3132 0.1197 1.1115
tau 0.5597 0.3460 1.0543
I^2(%) 92.2214 81.9177 97.6781
H^2 12.8558 5.5303 43.0680
Plots¶
import matplotlib.pyplot
from metafopy import forest, funnel
forest(res, atransf=numpy.exp)
matplotlib.pyplot.savefig('forest.png')
matplotlib.pyplot.figure()
funnel(res)
matplotlib.pyplot.savefig('funnel.png')
Plots draw on the current matplotlib figure and return a result object with the plotted values. See Plots.
Next steps¶
- Effect sizes lists the measures
escalcsupports and how to pool precomputed effects. - Fitting models covers estimators, tests, moderators and the methods you call on a fit.
- Analyses works through larger examples.