AdvancedIndependently reviewed, not yet spot-checked by a human

Forest and funnel plots

What each visual element of a forest plot encodes, what a high I² does and does not mean, the explanations for funnel plot asymmetry other than publication bias, which of the three asymmetry tests suits which kind of data, and what contour-enhanced funnels and trim-and-fill can and cannot tell you.

The forest plot: what each element encodes

A forest plot looks like a pile of dots and lines, but every visual element carries specific information:

ElementWhat it encodes
Each rowOne included study
Position of the boxThat study’s point estimate
Size of the boxThat study’s weight in the pooled estimate, usually inversely proportional to its variance
Horizontal lineThat study’s 95% confidence interval
Diamond at the bottomThe pooled estimate; its width is the confidence interval
Vertical reference lineThe null value (1 for ratio measures, 0 for difference measures)

Box size is the element most often ignored and the one carrying the most information. It tells you who is actually driving the pooled result. A common situation: one very large trial’s box is big enough to take most of the weight, while a dozen small studies together contribute little — at which point saying “we pooled fifteen studies” is somewhat misleading, because what you are really looking at is close to the result of that one large trial.

library(metafor)
library(metadat)

data(dat.bcg, package = "metadat")

# Turn the 2x2 tables into a log risk ratio and its variance for each trial
bcg <- escalc(measure = "RR",
              ai = tpos, bi = tneg, ci = cpos, di = cneg,
              data = dat.bcg, slab = paste(author, year, sep = ", "))

# Random-effects model (REML)
res <- rma(yi, vi, data = bcg, method = "REML")
res                                   # pooled estimate, I2, tau2, Q test

forest(res, atransf = exp,            # draw on the RR scale
       at = log(c(0.05, 0.25, 1, 4)),
       header = c("Trial", "Risk ratio [95% CI]"))

Verified with R 4.6.0, metafor 5.0.1 and metadat 1.6.0

A forest plot of 13 BCG vaccine trials. Most studies' confidence intervals lie to the left of the line of no effect and the pooled diamond sits left of 1, but the individual point estimates are spread over a wide range.
metadat::dat.bcg: 13 controlled trials of BCG vaccination against tuberculosis (only some of which allocated at random), random-effects model (REML). Notice how widely the individual point estimates are scattered — that is exactly the heterogeneity the next section is about.Plotting script figures/scripts/B7-04-forest-funnel.R

The pooled result is RR 0.49 (95% CI 0.34–0.70) across 13 studies. Every box and every horizontal line in that plot is one study’s log RR together with its variance — where those two numbers come from, and why it is the variance that decides how big the box is, is on effect measures and their variances.

Fixed effect and random effects ask different questions

The diamond above came out of a random-effects model, and which model drew it changes what it means: a fixed-effect diamond estimates one common true effect, a random-effects diamond estimates the mean of a distribution of study-specific effects. Reading a forest plot therefore starts with finding out which of the two produced the diamond — and with noticing that random effects also spreads the weights more evenly, so the boxes are not the sizes a fixed-effect plot would have drawn.

Which assumption is defensible for a given set of trials, what the choice costs in interval width, and which τ² estimator was used are the subject of fixed-effect and random-effects models; this page does not repeat them.

I²: it measures a proportion, not a magnitude

Most forest plots print I² beneath the diamond — here 92.2% — usually alongside the Q test (here Q = 152.2, df = 12, p = < 0.001). Both are quoted far more often than they are read correctly, and each has one standard misreading you need before the plot makes sense.

I² is the percentage of the total variation that is between-study variation — a ratio, so a large I² says nothing about how large the differences between studies actually are. For that, look at τ² (the between-study variance, 0.313 here) or at a prediction interval. And the Q test has very little power when the studies are few, so failing to reject its null is not evidence that the studies agree.

What each statistic does mean, the two estimators of I² that do not give the same number, and a simulation of how little power that Q test really has are all on heterogeneity: I², τ² and prediction intervals.

And the reason the BCG dataset is a teaching classic is that its heterogeneity has an explicable source: the latitude of the trial site. BCG works markedly better at higher latitudes (generally attributed to exposure to environmental non-tuberculous mycobacteria). That is the right way to handle heterogeneity — not to look for a way of suppressing it, but to find where it comes from and explain it with meta-regression or subgroup analysis.

Funnel plots and asymmetry

A funnel plot puts each study’s effect size on the x-axis against its precision on the y-axis (usually the standard error, inverted so that the precise studies sit at the top).

The logic is: in the absence of bias, large precise studies cluster near the true value (the neck of the funnel) and small imprecise studies scatter symmetrically on either side (the mouth), giving an inverted funnel shape.

A funnel plot of trials of intravenous magnesium in myocardial infarction. The small studies at the lower left are densely packed while the lower right is sparse, giving a clearly asymmetric shape.
metadat::dat.egger2001: 16 trials of intravenous magnesium in myocardial infarction. Dense at the lower left, sparse at the lower right — the classic case of funnel plot asymmetry.Plotting script figures/scripts/B7-04-forest-funnel.R

Egger’s test formalises the eyeballing: regress each study’s effect estimate on its own standard error and ask whether the slope differs from zero. A symmetric funnel puts that slope at zero — the estimate does not depend on how precise the study was; a slope away from zero says the smaller studies sit systematically to one side. (In this parameterisation the intercept is the other useful quantity: it is the pooled estimate extrapolated to a study of infinite precision, which is where the Egger-adjusted estimate mentioned below comes from. Egger’s original write-up regresses the standard normal deviate on precision instead, and there it is the intercept that carries the test — same test, different algebra, which is why sources disagree about which coefficient to read.)

Pooling this dataset gives OR 0.46 (95% CI 0.31–0.70), with an Egger test p < 0.0001. Its I² is 73.6%, so between-study variation is one of the possible sources that has to be considered when explaining this asymmetry; I² is a relative proportion of variance and cannot on its own settle either the absolute clinical size of the heterogeneity or the cause of the asymmetry.

The intercept of that same regression — the estimate extrapolated to a study of infinite precision — is OR 1.105 on this dataset, on the other side of the null. It is an extrapolation with no test attached to it, useful only for showing which way the data point.

This is one of the most famous episodes in the history of meta-analysis: a set of small trials consistently showed a significant benefit of intravenous magnesium in myocardial infarction, and pooling them produced a large apparent effect; the very large trial that followed (ISIS-4, with over fifty thousand participants) detected no protective effect — in this dataset its point estimate even falls to the right of 1. The funnel plot’s asymmetry was already a warning sign before the large trial was published.

Egger’s is not the only asymmetry test

Egger’s test is the one people cite, but it is neither the only one nor the right one for every outcome type. In practice you meet three tests and one sensitivity analysis. All four are aimed at the same thing — does the reported effect track how large the study was — and differ in what stands in for “large” and in how the regression is weighted.

Here is what they say about the magnesium trials (16 of them).

MethodWhat it actually computesStatisticpWhen to reach for it
Egger regression testWeighted regression of the effect estimate on its own standard error, testing the slopet = -5.78 (df = 14)p < 0.0001The default for continuous outcomes
Begg-Mazumdar rank correlation testKendall rank correlation between the standardised effect estimates and their variancesKendall τ = 0.150p = 0.4503Assumes no linear form, and pays for that with very low power
Peters regression testWeighted regression of the effect estimate on one over the total sample size, testing the slopet = -3.97 (df = 14)p = 0.0014Binary outcomes (OR, RR), where Egger’s test has a known bias
Trim-and-fillNot a test: imputes the studies a symmetric funnel would need, then re-pools7 imputed on the rightNo p-valueA sensitivity analysis: how far the pooled estimate could move

Egger’s known bias for binary outcomes is why Peters exists

Look again at the list of small-study effects above: the fourth entry is the mathematical dependence between the effect measure and its variance. For an OR or an RR that is not an abstract warning. The point estimate of the log OR and its standard error are computed from the same cells of the same 2x2 table, so a trial that happens to observe a larger effect also gets a larger estimated standard error. Regressing the effect on the standard error therefore has a non-zero slope built into it even when nothing is biased at all — most visibly when events are rare, the arms are unbalanced, or the true effect is large. Egger’s test inflates its type I error rate accordingly.

Peters replaces the predictor with a quantity that does not contain the observed effect: one over the total sample size. The weights change too, to an effective sample size built from the marginal totals of events and non-events rather than from the inverse variance of the effect measure. On the same data Egger gives p < 0.0001 and Peters gives p = 0.0014 — the same direction, but the Peters p-value is more than an order of magnitude larger, and part of that gap is the artefactual correlation just described.

The three tests disagree on the same dataset

On these 16 trials, Egger and Peters both flag asymmetry and the rank correlation test does not (p = 0.4503). That is not a contradiction, it is a difference in power: the rank test gives up the linearity assumption and pays for it by needing more studies to detect the same degree of asymmetry. A non-significant rank test cannot be used to argue against the other two — it simply did not detect anything.

Run the same four methods on the BCG dataset from the first half of this page and everything flips:

MethodMagnesium (16 trials)BCG (13 trials)
Egger regression testp < 0.0001p = 0.1887
Begg-Mazumdar rank correlation testp = 0.4503p = 0.9524
Peters regression testp = 0.0014p = 0.2302
Studies imputed by trim-and-fill71

On the BCG side all three tests detected no funnel plot asymmetry. That sentence cannot be extended: it is not the same as “there is no publication bias”, nor as “the funnel is symmetric”. There are only 13 studies here, sitting right on the Cochrane threshold below which asymmetry tests should not be run, and at that number all three tests have low power to begin with — low enough that “nothing detected” is close to the default outcome rather than information. Note also that the BCG dataset has an I² of 92.2%: extreme heterogeneity with no detectable asymmetry. Heterogeneity and funnel asymmetry are different things, and a high value of one does not imply a high value of the other.

Contour-enhanced funnels: which region the gap falls in

An ordinary funnel plot tells you where the gap is but not whether studies sitting in that gap would have been statistically significant — which is precisely the piece of information that decides whether the gap looks like publication bias. A contour-enhanced funnel paints the significance regions onto the background.

A funnel plot of the intravenous magnesium trials with the background divided into four significance regions: a white central wedge where p exceeds 0.10, then bands for 0.05 to 0.10, 0.01 to 0.05, and the outermost region where p is below 0.01. Most observed trials sit left of the null line and the lower right non-significant region is almost empty.
metadat::dat.egger2001: the same magnesium trials with significance contours added. The contours are centred on the null value (OR of 1), so each band answers the question of what p-value a study landing there would have.Plotting script figures/scripts/B7-04-forest-funnel.R

Centring the contours on the null is the whole point of the plot. Drawn around the pooled estimate instead — the default in several packages — the shading looks almost identical but answers a completely different question: how far each study sits from the pooled value, rather than whether each study was significant on its own.

There is only one reading rule, and it splits the five mechanisms into two piles:

  • The gap is in the non-significant region — consistent with publication bias. The studies that go unpublished are exactly the small ones that failed to reach significance.
  • The gap is in a significant region — publication bias does not explain it, because nobody suppresses a significant result. Look instead at heterogeneity, the methodological quality of small studies, the mathematical dependence between effect and variance, or plain chance.

Here is how this dataset falls out:

Significance regionLeft of the null (favours magnesium)Right of the null (favours control)Imputed by trim-and-fill
p < 0.01200
0.01 to 0.05400
0.05 to 0.10011
p > 0.10816

Of the 14 trials left of the null, 6 reach nominal significance; on the right there are only 2, and neither is significant. What is missing is the small trial pointing towards the control arm and failing to reach significance — the white region. That is the shape publication bias leaves behind, and it is why this dataset should have been unsettling before ISIS-4 was published.

Trim-and-fill imputes studies; it does not find them

The algorithm has three steps: trim off the extreme studies responsible for the asymmetry and re-estimate the pooled effect from what is left; mirror the trimmed studies across that new pooled value to fill in the other side; then re-pool using the completed set.

The same magnesium funnel plot, with filled points for the observed trials and open points for the seven studies trim-and-fill has imputed, all of them on the right. A dashed vertical line marks the pooled odds ratio from the observed trials alone and a solid line marks the pooled odds ratio after filling, visibly shifted towards the null.
metadat::dat.egger2001: the funnel after trim-and-fill has imputed 7 studies (open points). The two vertical lines are the pooled estimate before and after filling.Plotting script figures/scripts/B7-04-forest-funnel.R

On this dataset the algorithm imputes 7 studies, all on the right, taking the count from 16 to 23. The pooled OR moves from 0.465 to 0.676, 95% CI 0.443–1.031 — the adjusted interval crosses the null. A protective effect that looked settled no longer reaches statistical significance once the funnel is filled.

Read that carefully. It is not evidence that intravenous magnesium does not work, for three reasons:

  1. The 7 imputed points are not recovered studies. They have no patients, no event counts and no authors; they are coordinates the algorithm computed from a symmetry assumption. What the genuinely missing studies looked like, if they exist, nobody knows.
  2. It assumes the asymmetry comes from missing studies. If the asymmetry is really heterogeneity — this dataset has an I² of 73.6% — then the imputed studies are compensating for a gap that is not there and pushing the estimate in a direction nothing supports.
  3. It is sensitive to how τ² is estimated. Change the random-effects estimator and both the number imputed and the distance moved change with it.

So the output of trim-and-fill should be read as a conditional: if the asymmetry really is missing studies, the pooled estimate moves at most this far. That is one bound in a sensitivity analysis, not a corrected answer.

Applied to the BCG dataset the same procedure imputes only 1 study and moves the RR from 0.489 to 0.518 (95% CI 0.365–0.736), an interval that still excludes the null. When a funnel is not conspicuously asymmetric there is little for this algorithm to do — which is it behaving normally, not it confirming an absence of bias.

Run it yourself

library(metafor)
library(metadat)

data(dat.egger2001, package = "metadat")
mag <- escalc(measure = "OR", ai = ai, n1i = n1i, ci = ci, n2i = n2i,
              data = dat.egger2001, slab = study)
res <- rma(yi, vi, data = mag, method = "REML")

# 1. Egger: effect on standard error. The slope carries the test;
#    the intercept is the limit estimate at infinite precision
regtest(res, model = "lm")

# 2. Begg-Mazumdar: Kendall rank correlation of standardised effects
#    against their variances
ranktest(res)

# 3. Peters: predictor becomes 1/total sample size, weights become the
#    marginal event and non-event totals. metafor's
#    regtest(predictor = "ninv") swaps only the predictor and keeps 1/vi
#    weights, which is not Peters, so write out the published regression
a  <- dat.egger2001$ai
b  <- dat.egger2001$n1i - a
cc <- dat.egger2001$ci
d  <- dat.egger2001$n2i - cc
ni <- a + b + cc + d
wi <- 1 / (1 / (a + cc) + 1 / (b + d))
summary(lm(mag$yi ~ I(1 / ni), weights = wi))   # read the second row: slope

# 4. Trim-and-fill: not a test, a sensitivity analysis
tf <- trimfill(res)
tf                                    # k0 = how many imputed, side = which side
predict(tf, transf = exp)             # pooled estimate and interval after filling

# Contour-enhanced funnel. refline = 0 is the load-bearing argument: the
# contours must be centred on the null, because centred on the pooled
# estimate the same picture answers a different question
funnel(res, atransf = exp, refline = 0,
       level = c(90, 95, 99),
       shade = c("white", "gray88", "gray72"),
       legend = TRUE)

funnel(tf, atransf = exp)             # imputed studies get a different symbol

Verified with R 4.6.0, metafor 5.0.1 and metadat 1.6.0

Common misuses

MisuseWhy it is wrong
Claiming from I² that the differences in effect are large or smallI² is a proportion, not a magnitude, and is driven by how precise the studies are; absolute size means τ² or a prediction interval
Saying “there is no heterogeneity” because the Q test gives p > 0.05The Q test has very little power when there are few studies
Attributing funnel plot asymmetry directly to publication biasAt least four other explanations exist: heterogeneity, small-study quality, mathematical dependence, and chance
Running an asymmetry test on fewer than ten studiesInsufficient power; the result cannot be interpreted
Ignoring box size and treating “N studies pooled” as strength of evidenceThe weight may be concentrated in one or two of them
Switching to fixed effects to narrow the interval when heterogeneity is highModel choice follows from assumptions, not from the interval width you would prefer
Pooling studies that are not clinically comparableThe fact that they can be combined statistically does not make the number meaningful
Claiming there is no publication bias because the rank correlation test was not significantIt is the least powerful of the three; on the dataset used here it missed the asymmetry both other tests flagged
Treating the trim-and-fill adjusted estimate as a corrected truthThe added points are coordinates generated from a symmetry assumption, not studies that were recovered

Reproducing every number on this page

/opt/homebrew/bin/Rscript figures/scripts/B7-04-forest-funnel.R

Read the figure

The answer comes from the same statistical output that produced this page's figures, not from a number typed in beside them.

On the forest plot of these 13 BCG trials the pooled diamond sits at 0.489 with a 95% confidence interval of 0.344 to 0.696, entirely left of the null line, while the individual boxes are scattered widely. What is the width of the diamond telling you?

Show the answer and why

Correct answer: The ends of the diamond are the confidence interval for the mean effect, upper bound 0.696 — it says where the mean is, not where the next study would land, so a narrow diamond is not evidence that the studies agree

The ends of the diamond are the confidence interval of the pooled estimate, and that answers where the mean effect lies. The spread between studies is not inside it — the spread goes into τ², which reaches the diamond only indirectly through the weights and the standard error, and never stretches it far enough to cover where the studies sit. That is exactly how an I² of 92.221% and a narrow-looking diamond coexist: a narrow diamond says the mean is estimated precisely, not that the studies agree. The 0.313 is τ², the between-study variance of the log RR, and not the diamond's half-width; reading it as the half-width leaves the impression that the diamond has already drawn the heterogeneity. To see where the next study would land you need a prediction interval, which many forest plots add as a separate bar under the diamond.

The funnel plot for these 16 intravenous magnesium trials is dense at the lower left and sparse at the lower right, and the Egger test points firmly at asymmetry. Can that be written up as publication bias?

Show the answer and why

Correct answer: No. Asymmetry as a whole is called small-study effects and has at least five explanations, and this data has an I² of 73.640% — genuine heterogeneity alone is enough to produce it

Funnel asymmetry as a class is called small-study effects, and publication bias is only one of its explanations. The others are genuine heterogeneity (small trials recruiting higher-risk populations), poorer methodological quality in small studies, the mathematical dependence between effect size and variance for ORs and RRs, and plain chance when there are few studies. This data has an I² of 73.640%, so the heterogeneity route is open on its own, and all that can be written is that asymmetry was observed and is consistent with publication bias. The 1.105 is the regression extrapolated to infinite precision; it has no test of its own and only indicates which way the data points, not the true effect of studies nobody has seen. The 0.450 is the rank correlation p value, which genuinely detects nothing — but that test drops the linearity assumption and has very low power, so failing to detect cannot refute the other two tests. It can only say it did not detect.

On the same 16 trials with a binary outcome the Egger regression gives t = -5.78 and the Peters regression t = -3.97. They agree in direction, yet the Peters p value is an order of magnitude larger. How should that be read?

Show the answer and why

Correct answer: Peters returns 0.0014: it replaces the predictor with a quantity that does not contain the observed effect, whereas Egger's type I error rate is inflated on binary outcomes by the mathematical dependence between effect size and standard error

A log OR and its standard error are computed from the cells of the same two-by-two table, so a study that happens to observe a larger effect also picks up a larger standard error. Regressing effect on standard error therefore returns a non-zero slope even with no bias whatsoever, most visibly when event rates are low, the arms unbalanced and the true effect large — which inflates Egger's type I error rate, and is the reason Peters exists. Peters swaps the predictor for the inverse of the total sample size, a quantity that carries none of the observed effect, and the same data then returns 0.0014; part of the gap between the two is that artefactual correlation. The 0.2302 is the same Peters test moved to the BCG data, and it is large because that data has no marked asymmetry to begin with, not because Peters is inherently conservative. The 0.4503 is the rank correlation p value; picking the most conservative test when they disagree is choosing the test after seeing the result, whereas the test should be fixed in advance by the type of outcome — Peters for binary ones.

On the contour-enhanced funnel for the magnesium trials, 6 of the 14 studies on the left reach nominal significance, while the right holds only 2 and none of them is significant. What does that distribution support?

Show the answer and why

Correct answer: Of the seven imputed points, 6 fall in the non-significant region — what is missing is exactly the small, control-favouring, non-significant trials, and that shape is consistent with publication bias

The contours are drawn around the null value, so each band answers what p value a study landing there would obtain. There is one reading rule, and it splits the five mechanisms into two piles: a gap in the non-significant region is consistent with publication bias, because what goes unpublished is small studies that failed to reach significance, while a gap in the significant region is not, since nobody buries a significant result. Here 6 of the imputed points land in the non-significant region, and the hole is that white band. The 14 is the count observed on the left, and its size alone does not identify a cause — more on the left than the right simply is the asymmetry, and where the gap falls is what identifies its cause. The 23 is the post-fill total; the Cochrane rule about not testing asymmetry below ten studies counts studies actually collected, not coordinates an algorithm produced, and using imputed points to clear the threshold treats the output of a sensitivity analysis as new data. Consistent with publication bias is also not proof of it: this plot narrows the possibilities, it does not close the case.

Trim-and-fill adds seven studies to the magnesium data and moves the pooled OR from 0.465 to 0.676, 95% CI 0.443 to 1.031, now crossing the null. Does that show intravenous magnesium does not work?

Show the answer and why

Correct answer: No. The algorithm assumes the asymmetry comes from missing studies, and this data has an I² of 73.640% — if the asymmetry is heterogeneity instead, the imputed points compensate for a gap that is not there

The points trim-and-fill adds have no patients, no event counts and no authors; they are coordinates the algorithm computed from symmetry, so nothing has been recovered. It also assumes the asymmetry comes from missing studies, and this data has an I² of 73.640%, so the heterogeneity explanation stands on its own — in which case the imputed points compensate for a gap that does not exist and push the estimate in an unsupported direction. It is sensitive to how τ² is estimated too: change the estimator and both how many points appear and how far they sit will change. So the output reads as a conditional: if the asymmetry really is missing studies, this is the most the pooled estimate would move. The 1.105 is the extrapolation from the same regression and rests on the same assumption that asymmetry equals absence, so two numbers leaning on one assumption do not corroborate each other. The 0.518 is the same algorithm on the BCG data, filling little and moving little, which is its normal behaviour when the funnel was not markedly asymmetric — neither proof that the data is clean nor proof that the magnesium data is broken.

Moving the same four procedures to the 13 BCG trials gives Egger p = 0.1887, rank correlation 0.9524 and Peters 0.2302, none of them detecting asymmetry. What does that establish?

Show the answer and why

Correct answer: That heterogeneity and funnel asymmetry are separate things: this data has an I² as high as 92% and still no detectable asymmetry, so a high one does not imply a high other

All three tests failed to detect asymmetry, and the sentence stops there: it does not mean there is no publication bias, nor that the funnel is symmetric. This data holds 13 studies, right on the Cochrane threshold of 10 below which asymmetry tests are not advised, and at that count all three tests have low power — low enough that finding nothing is close to the default outcome rather than information. The rank correlation's 0.9524 makes the point best, since it is the least powerful of the three. What is genuinely informative is something else: the same data has an I² as high as 92%, extreme heterogeneity with no detectable funnel asymmetry, so the two are independent and a high one does not imply a high other. Trim-and-fill adding almost nothing is the same fact again: when the funnel was never markedly asymmetric the algorithm has little to do, which is normal behaviour rather than confirmation of anything.

Watch next

How to Interpret a Forest Plot
ENTerry Shaneyfelt· 6 minFive and a half minutes mapping every element of a forest plot to what it means. The cheapest possible preparation for this page.
醫學統計 EP18 統合分析:加權整合多項研究、看懂森林圖
繁中EDMAN MURMURS· 9 minA Traditional Chinese introduction, focused on why weighting is needed at all.
統合分析的異質性(Heterogeneity)
繁中杜裕康老師研究室· 11 minThe clearest Traditional Chinese treatment of heterogeneity there is, and a direct match for the third section of this page.
統合分析異質性和小樣本研究偏誤
繁中杜裕康老師研究室· 10 minFollows on from the previous video and makes the point that funnel plot asymmetry is not the same thing as publication bias — the same point as the fifth section here.

Sources and licences

This page is original writing

Report a content problem

The statistics on this site are written by AI and reviewed by AI; a human only spot-checks. What you can see may be what we cannot.

The more specific, the more fixable — e.g. which sentence disagrees with which textbook or paper.

Needed only if you want a reply; reports without it are still read.

Sent along with your report

These are attached automatically. You can drop any of them.