Skip to main content
ApexMed

Research & Publication

How to Conduct a Meta-Analysis in R: Step by Step

A practical, code-included walkthrough of running a meta-analysis in R with the metafor package — from PRISMA to forest plot to publication bias.

11 min read · 9/13/2026

A meta-analysis is one of the highest-yield publication types for a doctor or medical student without dedicated lab access — it needs a clear question, a rigorous search, and statistical competence, not a wet lab or patient recruitment. R, and specifically the metafor package, is the most widely used free toolchain for running one properly. This walkthrough covers the full pipeline, with real code, from question to publication-ready output.

Step 1: Form a Genuinely Answerable Question (PICO)

Before opening R, the question itself has to be narrow enough to actually answer. Use the PICO structure — Population, Intervention, Comparison, Outcome — and be specific. "Does drug X help diabetes" is not answerable; "In adults with type 2 diabetes (P), does drug X (I) compared to placebo (C) reduce HbA1c at 12 weeks (O)" is.

Mentor tip

The single most common reason a meta-analysis gets rejected at peer review isn't the statistics — it's a PICO question broad enough that the included studies are too clinically different to pool meaningfully in the first place.

Step 2: Systematic Search and the PRISMA Flow

Run your search across at least two databases (commonly PubMed and Embase, sometimes Scopus or Cochrane CENTRAL as a third), using the same search string logic across each. Document every number as you go: records identified, duplicates removed, records screened, full texts assessed, and studies finally included — this becomes your PRISMA flow diagram, which reviewers will check line by line against your reported study count.

  • PICO question defined and written down before searching
  • Search run across at least two databases with a documented search string
  • PRISMA flow numbers tracked at every stage (identified, screened, included)
  • Data extraction form prepared before opening the included papers
  • Risk-of-bias assessment tool selected (e.g. Cochrane RoB 2, Newcastle-Ottawa)

Step 3: Extract Your Data

For each included study you'll typically need: sample sizes, means and standard deviations (for continuous outcomes) or event counts (for binary outcomes), and enough study-level detail to assess risk of bias. Build this in a spreadsheet first — clean, one row per study — before it ever touches R.

Step 4: Load Your Data and Compute Effect Sizes in R

install.packages("metafor")
library(metafor)

# Example: continuous outcome, mean difference
dat <- escalc(
  measure = "MD",
  m1i = mean_treatment, sd1i = sd_treatment, n1i = n_treatment,
  m2i = mean_control,   sd2i = sd_control,   n2i = n_control,
  data = my_studies
)

escalc() computes the effect size and variance for each study from your raw extracted numbers — this is the step that turns a spreadsheet of study data into something metafor can actually pool.

Step 5: Fixed-Effect vs. Random-Effects — Choosing the Right Model

Fixed-Effect ModelRandom-Effects Model
AssumptionOne true effect size across all studiesTrue effect varies across studies
When appropriateStudies are clinically and methodologically very similarStudies differ in population, dose, or setting (the common case)
metafor functionrma(..., method = 'FE')rma(..., method = 'REML')
Typical use in practiceRare in clinical meta-analysisDefault choice for most published clinical meta-analyses
Choosing between the two core meta-analysis models

In practice, most clinical meta-analyses use a random-effects model by default, because it's rare for included studies to be similar enough in population and methodology to justify assuming one single true effect.

res <- rma(yi, vi, data = dat, method = "REML")
summary(res)

Step 6: Check Heterogeneity

The I² statistic tells you what proportion of the variation across studies is due to real differences between them rather than chance — metafor's summary() output reports this automatically alongside the Q-test p-value. As a rough guide, I² above 50% suggests substantial heterogeneity worth investigating (via subgroup analysis or meta-regression) rather than reporting a single pooled estimate as if the studies were interchangeable.

Step 7: Build the Forest Plot

forest(res, slab = paste(my_studies$author, my_studies$year))

The forest plot is the figure every reviewer looks at first — one row per study showing its effect size and confidence interval, with the pooled diamond at the bottom. Label rows clearly with author and year; a forest plot with unlabeled or cryptically labeled rows is a fast way to get a revision request.

Step 8: Check for Publication Bias

funnel(res)
regtest(res)

A funnel plot that looks asymmetric — small studies clustering on one side — is a warning sign that smaller negative studies may never have been published at all. Egger's test (regtest()) gives you a formal p-value for that asymmetry, and both the plot and the test are expected in a properly reported meta-analysis.

Watch out

Don't skip the publication-bias check even when your result "looks clean." Reviewers routinely ask for a funnel plot and Egger's test regardless of how the forest plot looks, and not including one is one of the most common reasons for a revise-and-resubmit.

Step 9: Report It Properly

Follow the PRISMA 2020 checklist when writing up the manuscript — it specifies exactly what needs to be reported, in what order, and most journals will ask for a completed PRISMA checklist as a submission requirement, not an optional extra.

Once you're comfortable with this pipeline on one dataset, the same structure — PICO, search, extraction, escalc(), rma(), forest plot, funnel plot — applies to essentially any meta-analysis question you take on next.

Dr. Haris Khan

Written by

Dr. Haris Khan

Want hands-on mentorship through your own meta-analysis?

The Master Meta-Analysis Card is a focused track in systematic review methodology and R-based evidence synthesis.

Explore the Meta-Analysis Card