Number Needed to Treat (and Number Needed to Harm)
The number of patients who must be treated for one additional patient to benefit, NNT = 1/ARR (the reciprocal of the absolute risk reduction over a stated time horizon); its harm analogue is NNH = 1/ARI (absolute risk increase), and both are baseline-risk- and time-dependent transformations of a risk difference.
In plain language
Number Needed to Treat (NNT) answers a simple, concrete question: how many patients do you have to give a treatment to, instead of the comparison, for one extra patient to avoid the bad outcome over a stated period of time? You get it by taking the gap in outcome risk between the two groups (the absolute risk reduction, ARR = comparison-group risk minus treated-group risk) and flipping it over: NNT = 1 / ARR, always rounded up to a whole patient. Its mirror image for a side effect is the Number Needed to Harm (NNH), computed the same way on a bad outcome. One honest caveat: the NNT is not a fixed property of the drug; it changes with how high the underlying risk is and with the length of the follow-up window, so a number from one population should not be copied onto another.
The number needed to treat (NNT) is the reciprocal of the absolute risk reduction (ARR): NNT = 1 / ARR, where ARR = risk_control - risk_treated over a stated time horizon. It answers the clinically concrete question "how many patients must receive the treatment, rather than the comparator, for one additional patient to avoid the (bad) outcome over this period?" Its mirror image for an adverse outcome is the number needed to harm (NNH) = 1 / ARI, where ARI = the absolute risk increase = risk_treated - risk_control. Both are simply the absolute risk difference rendered on a more interpretable scale: an ARR of 0.05 (a 5-percentage-point reduction) is an NNT of 20, an ARR of 0.01 an NNT of 100. NNT is always rounded up to the next whole patient (you cannot treat a fraction of a person to prevent a fraction of an event), and it carries the sign/direction of the outcome — a "negative NNT" is properly an NNH and should be reported as such, not as a negative number.
Core conceptual distinction — NNT is not a property of the treatment alone
Unlike a relative measure (relative risk, hazard ratio, odds ratio), which is often approximately stable across baseline-risk strata, the NNT is a function of the baseline risk because ARR = baseline_risk (1 - RR). The same relative risk reduction yields a small NNT in a high-risk population and a huge NNT in a low-risk one: a treatment with RR = 0.75 (a 25% relative reduction) gives ARR = 0.05 and NNT = 20 when baseline risk is 0.20, but ARR = 0.0025 and NNT = 400 when baseline risk is 0.01. This is precisely why an NNT computed by applying a published relative measure requires you to supply the baseline risk of your* population — transporting an NNT from a trial to a real-world population without re-anchoring it to the local baseline risk is a category error. NNT is also time-horizon dependent: it is meaningful only attached to the follow-up window over which the risks were measured (a 1-year NNT and a 5-year NNT for the same therapy differ), and for time-to-event data it should be derived from the cumulative incidence (risk) at the chosen horizon, not from a hazard ratio treated as if it were a risk ratio.
Pros, cons, and trade-offs
- vs relative risk / hazard ratio (`hazard-ratio-interpretation` family): The NNT (and its parent, the ARR) conveys the absolute clinical and budgetary impact a relative measure hides — a "50% reduction" is impressive whether baseline risk is 40% or 0.04%, but the NNT (1.25 vs 1250) tells you whether it matters. Prefer the NNT/ARR for clinical and HTA communication of magnitude; prefer the relative measure for transporting effects across populations and for modeling, because it is more stable across baseline-risk strata. Report both: a relative effect plus a baseline-anchored NNT. - vs reporting the ARR (risk difference) directly: The NNT is the ARR's reciprocal and contains exactly the same information, but the reciprocal transformation is non-linear and badly behaved near ARR = 0, which is why the confidence interval for the NNT is the reciprocal of the ARR's CI limits and inherits a pathology (below). Prefer reporting the ARR with its CI as the primary quantity and the NNT as the interpretable gloss, especially when the effect is not clearly significant. - vs NNH and a combined benefit-harm view: NNT (benefit) and NNH (harm) are computed identically but on different outcomes; comparing them (or combining them into a likelihood-of-being-helped-vs-harmed, LHH = NNH/NNT) frames the net clinical trade-off. Use NNT and NNH together whenever a therapy has both a benefit and a non-trivial harm; reporting NNT alone for an efficacious-but-toxic drug is misleading.
When to use
Translating an absolute risk difference into a clinically and economically interpretable count for guideline panels, HTA dossiers, and shared decision-making; expressing the magnitude (not just the direction) of a comparative effect from an RWE study after the absolute risks have been estimated correctly (e.g., from a cumulative incidence function or a marginal/standardized risk under competing risks); summarizing benefit and harm on a common scale (NNT and NNH) to support a net-benefit judgment.
When NOT to use — and when it is actively misleading or dangerous
- When the confidence interval for the ARR includes zero. This is the notorious NNT discontinuity problem: if the ARR CI is (-0.01, +0.05) it spans zero, so the NNT CI is not a finite interval — it runs from a positive NNT (benefit) through plus/minus infinity to a negative NNT (harm, i.e., an NNH). Reporting a tidy "NNT 20 (95% CI 12 to 50)" when the effect is not significant fabricates a finite, benefit-only interval and hides that the data are compatible with harm. When the ARR is non-significant, report the ARR CI and state the NNT only with the Altman (1998) convention (NNT_benefit ... infinity ... NNT_harm), or do not report an NNT at all. - Transporting an NNT across populations. Because the NNT depends on baseline risk, a trial NNT does not apply to a real-world population with a different baseline risk; re-anchor by combining the (more transportable) relative effect with the local baseline risk. - Quoting an NNT without its time horizon. An NNT detached from the follow-up window over which the risks were measured is uninterpretable and invites comparison of NNTs measured over different horizons. - Deriving an NNT from a hazard ratio as if it were a risk ratio, ignoring competing risks. With non-trivial competing mortality, the cause-specific hazard does not translate into the absolute risk a patient experiences; compute the NNT from cumulative incidence functions at the horizon, not from a HR (see `competing-risks-cause-specific-fine-gray-rwe`).
Data-source operational depth
- Claims (FFS): The two absolute risks that define the ARR are themselves cumulative incidences that must be estimated on a correctly constructed at-risk denominator. Build them on FFS-observable person-time only; Medicare Advantage enrollees generate no claims, so MA-only spans produce fabricated "event-free" follow-up that biases the absolute risks and therefore the ARR and NNT. With an active-comparator new-user design and PS matching/weighting, derive the marginal (standardized) absolute risks in each arm; an NNT built on a crude, unadjusted risk difference inherits confounding by indication. State the time horizon explicitly and handle the competing risk of death with cumulative incidence functions. - EHR: Encounter-driven ascertainment makes event-free time partly unobserved (out-of-system care), biasing the absolute risks; require an "active in system" definition and treat informative loss to follow-up with appropriate censoring before estimating risks and the NNT. - Registry / linked: Adjudicated registry outcomes and a linked death index give the cleanest absolute risks (and an honest competing-risk denominator), making linked claims-EHR-vital-records the strongest substrate for a defensible NNT; linkage selects the linkable subset, so the baseline risk that anchors the NNT is the linked-cohort baseline.
Worked claims example
In an active-comparator new-user cohort (drug A vs drug B) for a non-fatal cardiovascular outcome over a 2-year horizon, 1:1 PS matching balances baseline covariates and the marginal (standardized) 2-year cumulative incidences from competing-risk-aware estimation are risk_B (comparator) = 0.120 and risk_A (treated) = 0.090. Then the ARR = 0.120 - 0.090 = 0.030 (3 percentage points over 2 years) and the NNT = 1 / 0.030 = 33.3, rounded up to 34: 34 patients treated with A rather than B for one additional patient to avoid the event within 2 years. Suppose the ARR's 95% CI is (0.008, 0.052) — it excludes zero, so the NNT CI is the (reversed) reciprocal of those limits: 1/0.052 = 19.2 and 1/0.008 = 125, i.e., NNT 34 (95% CI 20 to 125), all on the benefit side, reported with the 2-year horizon. Now contrast the dangerous case: had the ARR CI been (-0.004, 0.052), it would span zero, and the honest NNT statement is "NNT_benefit 19 to infinity, then NNT_harm 250 to infinity" (Altman convention) — not "NNT 34 (95% CI 20 to ...)", which would conceal that the data are compatible with net harm. Finally, to transport this finding to a lower-risk primary-prevention population with baseline 2-year risk 0.04 under the same relative effect (RR = 0.090/0.120 = 0.75), the re-anchored ARR = 0.04 * (1 - 0.75) = 0.010 and the NNT must be recomputed against the local baseline rather than carried over.
Interpreting the output
A propensity-score-matched RWE study comparing Drug A vs Drug B in 1,000 patients per arm over a 2-year window yields marginal cumulative incidence estimates of 0.090 (treated) and 0.120 (comparator), an ARR of 0.030, and an NNT of 34 (95% CI 20 to 125) over 2 years at a baseline risk of 12%.
(1) Formal interpretation. The NNT of 34 means that, under this study's conditions, 34 patients would need to receive Drug A instead of Drug B for one additional patient to avoid the outcome within the 2-year follow-up window — at the observed comparator-arm baseline risk of 12% (0.120). The NNT is the reciprocal of the ARR (1 / 0.030 = 33.3, rounded up to 34), and its confidence interval is the reversed reciprocal of the ARR interval limits (1/0.052 ≈ 19; 1/0.008 = 125). The NNT is not a property of the drug alone; it is specific to this 2-year horizon and this 12% baseline risk. Applying this NNT to a lower-risk primary-prevention population with a 4% baseline risk would require re-anchoring — under the same relative effect (RR ≈ 0.75), the NNT rises to approximately 100.
(2) Practical interpretation. An NNT of 34 over 2 years is a concrete, audience-ready summary of benefit magnitude. For a formulary committee weighing Drug A versus Drug B, it translates directly into budget terms: treating 34 patients for 2 years prevents one event. Always pair the NNT with the time horizon (2 years), the baseline risk (12%), and the outcome definition — a horizon-free NNT is uninterpretable and should not appear in a submission or decision brief.
Worked example
Scenario
We compared two groups of 1,000 patients each over a 2-year window: one group got drug A (treated), the other got drug B (the comparison). We counted how many patients in each group had a heart-related event, turned those counts into a risk for each group, and now want the NNT: how many patients we would have to treat with drug A instead of drug B for one extra patient to avoid the event within 2 years.
Dataset
A small summary table an analyst would build after counting events in each treatment arm over the 2-year window.
| arm | n | events | risk |
|---|---|---|---|
| control (drug B) | 1000 | 120 | 0.12 |
| treated (drug A) | 1000 | 90 | 0.09 |
Steps
Turn each arm's event count into a risk: control = 120 / 1000 = 0.12, treated = 90 / 1000 = 0.09.
Find the absolute risk reduction (ARR) by subtracting the treated risk from the control risk: ARR = 0.12 - 0.09 = 0.03 (a 3-percentage-point drop over 2 years).
Flip the ARR to get the NNT: NNT = 1 / 0.03 = 33.3.
Round up to a whole patient, because you cannot treat a fraction of a person: NNT = 34.
Result
ARR = 0.12 - 0.09 = 0.03, so NNT = 1 / 0.03 = 33.3, rounded up to 34. About 34 patients must be treated with drug A instead of drug B for one extra patient to avoid the event within the 2-year window.
Runnable example
python implementation
Compute the NNT (or NNH) and its confidence interval from two arm-specific absolute risks with event counts, handling the discontinuity when the ARR CI spans zero (Altman 1998). Inputs: events and N in the treated and control arms over a stated horizon....
import numpy as np
from scipy.stats import norm
def nnt(events_t, n_t, events_c, n_c, conf=0.95):
"""NNT/NNH with an ARR-based CI; handles the discontinuity when the ARR CI spans 0."""
r_t = events_t / n_t # treated risk
r_c = events_c / n_c # control risk
arr = r_c - r_t # absolute risk reduction (benefit if > 0)
se = np.sqrt(r_t*(1-r_t)/n_t + r_c*(1-r_c)/n_c)
z = norm.ppf(1 - (1-conf)/2)
lo, hi = arr - z*se, arr + z*se # ARR confidence limits
point = np.inf if arr == 0 else 1.0 / arr
label = "NNT (benefit)" if arr > 0 else ("NNH (harm)" if arr < 0 else "no effect")
out = {"ARR": arr, "ARR_CI": (lo, hi), "point": point, "label": label,
"NNT_rounded": int(np.ceil(abs(point))) if np.isfinite(point) else None}
if lo <= 0 <= hi: # discontinuity: CI compatible with harm
out["NNT_CI"] = "NNT_benefit {} to inf, then NNT_harm {} to inf".format(
round(1/hi) if hi > 0 else "n/a", round(abs(1/lo)) if lo < 0 else "n/a")
out["significant"] = False
else: # finite interval; reciprocal swaps limit order
out["NNT_CI"] = tuple(sorted((abs(1/lo), abs(1/hi))))
out["significant"] = True
return out
# Worked example: treated 90/1000 (0.090), control 120/1000 (0.120) over 2 years.
res = nnt(events_t=90, n_t=1000, events_c=120, n_c=1000)
print(f"ARR = {res['ARR']:.3f} -> {res['label']} = {res['NNT_rounded']} "
f"(95% CI {res['NNT_CI']}), significant={res['significant']}")r implementation
NNT/NNH and its confidence interval from two arm-specific risks in base R, with explicit discontinuity handling per Altman (1998). The 95% CI for the ARR (Wald) is inverted to the NNT scale; when the ARR CI crosses zero the function returns the...
nnt <- function(events_t, n_t, events_c, n_c, conf = 0.95) {
r_t <- events_t / n_t # treated risk
r_c <- events_c / n_c # control risk
arr <- r_c - r_t # absolute risk reduction
se <- sqrt(r_t*(1-r_t)/n_t + r_c*(1-r_c)/n_c)
z <- qnorm(1 - (1-conf)/2)
lo <- arr - z*se; hi <- arr + z*se # ARR confidence limits
point <- if (arr == 0) Inf else 1/arr
label <- if (arr > 0) "NNT (benefit)" else if (arr < 0) "NNH (harm)" else "no effect"
if (lo <= 0 && 0 <= hi) { # discontinuity: compatible with harm
ci <- sprintf("NNT_benefit %s to Inf, then NNT_harm %s to Inf",
ifelse(hi > 0, round(1/hi), "n/a"),
ifelse(lo < 0, round(abs(1/lo)), "n/a"))
sig <- FALSE
} else { # finite interval; reciprocal reverses limits
ci <- sort(abs(c(1/lo, 1/hi))); sig <- TRUE
}
list(ARR = arr, ARR_CI = c(lo, hi), label = label,
NNT = ceiling(abs(point)), NNT_CI = ci, significant = sig)
}
# Worked example: treated 90/1000 (0.090), control 120/1000 (0.120) over 2 years.
res <- nnt(90, 1000, 120, 1000)
cat(sprintf("ARR = %.3f -> %s = %d (95%% CI %s)\n",
res$ARR, res$label, res$NNT, paste(round(res$NNT_CI), collapse = " to ")))