Skip to main content
v2026.11,772 entries · CC-BY 4.0

Poisson and Negative Binomial Regression in Stata

Fitting poisson and nbreg for count outcomes in Stata: using exposure() to model rates, testing for overdispersion, and reporting results as incidence-rate ratios.

Written and maintained by CASRAI Editorial Board

Last updated

Stata fits count-outcome regression two ways that get treated as interchangeable when they aren’t: poisson, which assumes the outcome’s variance equals its mean, and nbreg (negative binomial), which adds a dispersion parameter for when it doesn’t. Fitting the wrong one rarely moves the point estimates much — it moves how much you can trust them. On overdispersed count data, poisson‘s standard errors, confidence intervals, and p-values are all systematically too small, which means a coefficient that looks solidly significant under poisson can lose significance entirely under nbreg. This guide covers fitting both commands, testing which one your data actually needs, using exposure() to model rates instead of raw counts, and reporting results as incidence-rate ratios.

Fitting the base model with poisson

The syntax follows the same pattern as any other Stata estimation command:

poisson case_count predictor1 predictor2 i.category_var

The default output reports a coefficient table on the log scale — a coefficient of 0 means no association with the expected count, a positive coefficient means the predictor raises it. Almost no one reports the raw log-scale coefficient in a write-up; add , irr to the command to redisplay the same fitted model with exponentiated coefficients — incidence-rate ratios — without refitting:

poisson case_count predictor1 predictor2 i.category_var, irr

This is the same coefficient/exponentiated-coefficient relationship logit and logistic have for the binary case: one estimation, two display scales, switch between them with irr or Stata’s general eform option rather than fitting twice.

Modeling rates, not just raw counts: exposure() and offset()

A plain poisson model assumes every observation had equal opportunity to generate an event. That assumption breaks the moment the units being compared differ in size or follow-up time — one hospital unit’s infection count covers 200 patient-days, another’s covers 900; one country’s case count covers a population of 2 million, another 40 million. Comparing raw counts across units like that is comparing the wrong thing.

The fix is the exposure() option:

poisson case_count predictor1 predictor2, exposure(patient_days) irr

This adds ln(patient_days) to the model as an offset term with its coefficient fixed at exactly 1, which converts what the model predicts from a raw count to a rate per unit of exposure. If you’ve already computed the log of the exposure variable yourself — for instance because it needs to be constructed from more than one field — use offset(ln_patient_days) instead and pass the already-logged variable directly. The two options do the same thing; exposure() just takes the logarithm for you and expects the raw (unlogged) variable.

The same option works identically on nbreg once you get there — exposure/rate modeling and the Poisson-vs-negative-binomial choice are independent decisions, not alternatives to each other.

Testing whether you actually need negative binomial: overdispersion

The Poisson distribution has one property that does most of the work here: its variance is mathematically forced to equal its mean. Real count data routinely violates that — extra clustering, unmeasured heterogeneity between subjects, or a genuinely different underlying process all push the variance above the mean, a pattern called overdispersion. A quick, informal check compares the mean and variance of the outcome directly (summarize case_count, detail or tabstat case_count, stat(mean sd) and square the SD); if variance is noticeably larger than the mean, that’s an early flag, not a formal test.

The formal test comes from fitting nbreg and reading its own output, covered next — Stata prints a likelihood-ratio test of overdispersion automatically after every nbreg run, which is the test to trust over an informal mean/variance comparison.

Fitting negative binomial with nbreg

nbreg case_count predictor1 predictor2, exposure(patient_days) irr

Stata’s default nbreg fits the NB2 parameterization, where the variance grows quadratically with the mean (variance = mean + α × mean²). At the bottom of the output, nbreg prints a line reading approximately Likelihood-ratio test of alpha=0: chibar2(01) = ... Prob>=chibar2 = 0.000. α is the dispersion parameter this test is checking: a small p-value on that line means α is significantly different from 0, i.e. real overdispersion is present and the wider standard errors nbreg produces are the honest ones — poisson‘s narrower intervals on the same data were overconfident. If that test is not significant, α is statistically indistinguishable from 0, poisson was an adequate model for the data, and nbreg hasn’t added anything except a less efficient estimate of the same relationship.

Because α=0 sits on the boundary of what’s a valid value (dispersion can’t be negative), the printed test already uses a boundary-adjusted chi-bar-squared reference distribution rather than an ordinary chi-square(1) — the standard fix from Cameron and Trivedi’s count-data econometrics work, and the reason this specific test is reported directly in the command’s own output instead of being left for the user to run a generic lrtest between two separately fitted models afterward. Use the number nbreg prints, not a manual likelihood-ratio comparison against a separately fit poisson model.

For the mechanics of the dispersion parameter itself — NB1 vs. NB2 variance structures, and when each is the more natural fit — see Negative Binomial Regression: The Overdispersion Fix, the software-agnostic companion to this page.

Reading and reporting incidence-rate ratios

With irr in the command (or run afterward as poisson, irr / nbreg, irr without refitting), each predictor’s row reports exp(coefficient) instead of the raw log-scale coefficient. An IRR of 1.0 means no association; an IRR of 1.35 means a one-unit increase in that predictor is associated with a 35% higher expected rate, holding the other predictors constant; an IRR of 0.80 means a 20% lower rate. This is a genuinely different quantity from an odds ratio and shouldn’t be described with odds-ratio language in a write-up — see Incidence Rate Ratio for the full distinction and a worked example of where the two get conflated.

For a predicted count or rate at specific covariate values — rather than a relative comparison — margins works the same way after poisson/nbreg as it does after any other Stata estimation command:

margins, at(predictor1=(10 20 30)) predict(n)

predict(n) asks for the predicted count/rate scale rather than the linear (log) index that margins defaults to; predict(ir) is available too if the model includes an exposure()/offset() term and the predicted incidence rate itself is the quantity of interest, distinct from the exposure-adjusted predicted count.

When neither poisson nor nbreg is the right tool

Both commands assume the outcome can, in principle, be 0 through any count with no ceiling. Two common departures each have their own dedicated Stata command rather than a modification of poisson/nbreg: a dataset with far more zeros than either distribution predicts calls for a zero-inflated model (zip/zinb); repeated counts on the same subject or cluster, where observations aren’t independent, calls for generalized estimating equations or a mixed-effects count model instead of assuming independence across rows. Fitting nbreg on clustered data addresses overdispersion but not the correlation structure — they’re two separate violations of the plain Poisson model’s assumptions, and fixing one doesn’t fix the other.

Frequently asked questions

Should I always run nbreg instead of poisson, just to be safe?

Not by default. nbreg estimates an extra parameter (α) that poisson doesn’t, which costs efficiency when it isn’t needed — on data that’s genuinely equidispersed, poisson‘s estimates are more precise for the same sample size. Run poisson first, check the overdispersion test from nbreg‘s own output, and let that test decide rather than defaulting to the more complex model out of caution.

My data has more zeros than either model predicts — is that overdispersion?

Not necessarily the same problem. Excess zeros can produce apparent overdispersion, but the fix isn’t automatically nbreg — if the zeros come from a genuinely separate process (e.g. some subjects can never have any events, versus subjects who can but happened to have zero this period), a zero-inflated model (zip or zinb) is the better-specified tool. Compare a histogram of the outcome against what a Poisson or negative binomial distribution with the same mean would predict before assuming nbreg alone resolves it.

Can I use exposure() with nbreg, not just poisson?

Yes — exposure() and offset() work identically on both commands. The rate-vs-count decision (does exposure time differ meaningfully across observations?) and the Poisson-vs-negative-binomial decision (is the data overdispersed?) are independent questions; answer both rather than assuming one implies the other.

Why does Stata’s nbreg overdispersion test use chibar2 instead of a normal chi-square?

Because the null hypothesis being tested (α=0) sits on the boundary of α’s valid range — a dispersion parameter can’t be negative — the usual chi-square(1) reference distribution isn’t appropriate. Stata reports the boundary-corrected chi-bar-squared version automatically as part of standard nbreg output, so this doesn’t require any extra step; just read the Prob>=chibar2 line at the bottom of the results.

Related CASRAI resources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · included with Regulatory Radar

Ask about Poisson and Negative Binomial Regression in Stata

Ask CASRAI answers research-administration questions and cites the passages behind every claim — and says so when the corpus does not cover something, instead of guessing. It comes with a Regulatory Radar subscription at $29 a month, alongside the daily digest of regulatory changes and the dashboard of what changed.

150 questions a day, on this site, over the API, or inside your own tools through the CASRAI MCP server.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Regulatory Radar

Stop finding out after the fact

$29/month, cancel anytime. Daily digest updates from our analysis, a dashboard holding the same items, and a cited assistant for everything they raise.

  • Federal Register, Federal Register+, Grants.gov, Regulations.gov, NSF News, UKRI, plus CASRAI’s own published content.
  • 72,264 indexed passages, and every answer cites the ones it drew on.