May 30, 2026 · 6 min read

How to Create a Forest Plot for Publication

A complete guide to creating publication-quality forest plots: structure, effect sizes, confidence intervals, heterogeneity, and export for meta-analysis and clinical research.

Forest plots are the standard visualization for meta-analyses, subgroup analyses, and clinical trial results. They display effect estimates and confidence intervals for multiple studies or subgroups simultaneously, with a diamond showing the pooled estimate. A well-constructed forest plot is immediately interpretable; a poorly made one raises reviewer concerns about the analysis itself.

What a forest plot shows

A forest plot displays:

  • Left column: Study or subgroup labels
  • Center panel: Horizontal lines (confidence intervals) with a square (point estimate) for each study; square size = statistical weight
  • Right columns: Numerical data (effect size, 95% CI, weight, p-value)
  • Diamond: Pooled effect estimate across all studies (width = 95% CI of pooled estimate)
  • Vertical reference line: The null value (1.0 for ratio measures; 0 for difference measures)

Step 1 — Organize your data

You need at minimum:

  • Study/subgroup label
  • Point estimate (odds ratio, hazard ratio, risk ratio, mean difference, or standardized mean difference)
  • Lower 95% CI bound
  • Upper 95% CI bound
  • Optional: sample size (N), weight (%), events

For a meta-analysis, these come from your meta-analysis software (R meta, metafor, RevMan). For a subgroup analysis from a single study, these come from your regression output.

Step 2 — Choose the correct effect measure

Study type Effect measure Null value
Case-control, cohort Odds ratio (OR) 1.0
Survival analysis Hazard ratio (HR) 1.0
RCT, cohort Risk ratio (RR) 1.0
Continuous outcomes Mean difference (MD) 0
Standardized outcomes SMD (Cohen's d) 0

Log scale for ratio measures: OR, HR, and RR should be plotted on a log scale so the visual distance for a 2× increase equals the distance for a 0.5× decrease (symmetry). On a linear scale, ORs > 1 look artificially stretched.

Step 3 — Construct the forest plot

Standard layout (left to right):

  1. Study label column (left-aligned)
  2. Subgroup or year column (optional)
  3. Forest plot panel (center)
  4. Effect size column
  5. 95% CI column
  6. Weight column (for meta-analysis)
  7. P-value column (optional)

Square size: Proportional to the statistical weight of each study (inverse variance weight in fixed-effects; heterogeneity-adjusted in random-effects).

Reference line: A solid vertical line at null (1.0 or 0). Some journals prefer a dashed line.

Summary diamond: The horizontal extent of the diamond = 95% CI of the pooled estimate. Center of the diamond = point estimate.

Step 4 — Report heterogeneity (for meta-analysis)

Every forest plot for a meta-analysis must report:

  • I² statistic: Percentage of variance attributable to heterogeneity; I² > 50% is considered substantial
  • Cochran's Q test p-value: P-value for the null hypothesis of homogeneity
  • Tau²: Variance of the true effects in a random-effects model

State whether you used a fixed-effects or random-effects model and justify the choice based on I².

Place heterogeneity statistics below the forest plot: "Heterogeneity: I² = 52%, Q = 18.4, p = 0.018; τ² = 0.03"

Step 5 — Subgroup analyses

If showing multiple subgroups within one forest plot:

  • Group rows visually (indent subgroup studies under the subgroup header)
  • Show a summary diamond for each subgroup
  • Show the test for subgroup differences (interaction p-value): "P for interaction = 0.04"
  • Avoid testing too many subgroups — pre-specify them

Code examples

R (meta + forest.meta):

library(meta)

m <- metagen(TE = log(OR), seTE = SE, studlab = Study,
             sm = "OR", method.tau = "REML")

forest(m,
  leftlabs = c("Study", "Year"),
  rightlabs = c("OR", "95% CI", "Weight"),
  print.tau2 = TRUE,
  print.I2 = TRUE,
  col.diamond = "#2166AC",
  col.square = "#4D4D4D",
  fontsize = 9,
  colgap.forest = unit(3, "mm"))

R (forestplot package for custom layouts):

library(forestplot)

forestplot(labeltext = cbind(Study, OR_formatted, CI_formatted),
  mean = log_OR, lower = log_lower, upper = log_upper,
  zero = 0,  # null on log scale
  is.summary = is_summary_row,
  col = fpColors(box = "#4D4D4D", summary = "#2166AC"),
  xlog = TRUE,  # display on log scale
  graphwidth = unit(50, "mm"))

Formatting for publication

  • Figure width: Single-column (85–89 mm) for 5–10 studies; full-width (170–183 mm) for ≥15 studies
  • Font: Arial/Helvetica, minimum 7 pt at print size
  • X-axis limits: Choose to show all confidence intervals fully — do not truncate CIs
  • Favor label: Add "Favors control ← → Favors treatment" beneath the x-axis
  • Overall estimate: Label clearly as "Pooled effect (Fixed)" or "Pooled effect (Random)" depending on model

Common mistakes

  • Linear scale for OR/RR/HR — makes the visualization asymmetric and misleading
  • Missing heterogeneity statistics — required by all journals for meta-analysis
  • Not justifying fixed vs random effects — reviewers will ask
  • Truncating confidence intervals — must show complete CIs; use extended x-axis
  • Inconsistent column alignment — use fixed-width fonts or tabular formatting for numerical columns

FAQ

Should I use a fixed-effects or random-effects model? Use random-effects when I² > 0 or when there is clinical/methodological heterogeneity between studies (which is almost always the case). Fixed-effects is only appropriate when studies are truly identical in design and population.

What is a good I² value? I² < 25% is considered low heterogeneity, 25–50% is moderate, and > 50% is substantial. However, I² depends on the number of studies — in a meta-analysis of 5 small studies, even substantial heterogeneity may have a non-significant Q test.

Can forest plots be used for subgroup analyses of a single study? Yes. Forest plots are appropriate for any analysis presenting multiple estimates of the same outcome — subgroup analyses, sensitivity analyses, or coefficient plots from a single model.

How do I make a forest plot without meta-analysis software? Use R's ggplot2 with geom_pointrange() or the ggforestplot package. For a clean table-style layout with the plot, use forestplot or forestploter.

Build publication-quality forest plots in FigureGuild → Start free