AdvancedIndependently reviewed, not yet spot-checked by a human

Logistic regression and the odds ratio

Which ratio an OR actually is, why it necessarily overstates the effect when the outcome is not rare, how an adjusted OR differs from a crude one for reasons other than confounding, what separation looks like and how to fix it, and where the "at least ten events per variable" rule came from and why it is now disputed.

What this model is for

The second large family of clinical outcomes is binary: low birth weight or not, hospital-acquired infection or not, readmission within thirty days or not, a postoperative complication or not.

Fitting a 0/1 outcome with linear regression breaks in two places: fitted values leave the 0–1 range (a negative probability means nothing), and the residual variance changes with the fitted probability (the variance of a 0/1 variable is p(1p)p(1-p), which is not constant by construction).

Logistic regression fixes this by changing the scale first. Turn the probability pp into the odds p/(1p)p/(1-p), then take the logarithm; the range opens from [0,1][0,1] out to the whole real line, and the linear model is built there:

logp1p=β0+β1x1++βkxk\log \frac{p}{1-p} = \beta_0 + \beta_1 x_1 + \cdots + \beta_k x_k

So each β\beta means “with the other variables held constant, a one-unit increase in xx raises the log-odds by β\beta”, and exponentiating gives exp(β)\exp(\beta), the odds ratio (OR). This model produces an OR rather than an RR not because anyone chose it, but because of how the model is built.

The example on this page

We keep MASS::birthwt from the linear regression page and switch the outcome to the binary low: whether the newborn weighed under 2500 g. Of 189 mothers, 59 had a low-birth-weight baby, a prevalence of 31.2%.

That prevalence is the reason this example was chosen. It is nowhere near rare, so the OR and the RR will visibly part company in the same table — which is what the next section is about.

library(MASS)
data(birthwt, package = "MASS")

bw <- birthwt
bw$race_f  <- factor(bw$race,  levels = 1:3, labels = c("White", "Black", "Other"))
bw$smoke_f <- factor(bw$smoke, levels = 0:1, labels = c("No", "Yes"))
bw$ptl_any <- as.integer(bw$ptl > 0)

# Crude OR: one predictor
fit_c <- glm(low ~ smoke_f, data = bw, family = binomial)
exp(cbind(OR = coef(fit_c), confint.default(fit_c)))

# The RR from the same 2x2 -- you compute it yourself, glm will not give it
tb <- table(bw$smoke_f, bw$low)
(tb[2, 2] / sum(tb[2, ])) / (tb[1, 2] / sum(tb[1, ]))

# Adjusted OR
fit <- glm(low ~ smoke_f + age + lwt + race_f + ht + ui + ptl_any,
           data = bw, family = binomial)
summary(fit)
exp(cbind(OR = coef(fit), confint.default(fit)))   # Wald, the format papers use

# What separation looks like: treat ptl as a four-level factor
summary(glm(low ~ smoke_f + factor(ptl), data = bw, family = binomial))

Verified with R 4.6.0 and MASS 7.3.65. For a glm, confint() returns profile-likelihood intervals; the Wald intervals papers usually report come from confint.default().

Crude OR and RR: one 2×2 table, two answers

Before fitting anything, do it by hand. Smoking against low birth weight:

Low birth weightNormalTotalRiskOdds
Smoked30447440.5%0.682
Did not smoke298611525.2%0.337
  • Risk ratio (RR) = one risk divided by the other = 1.608 (1.06–2.44)
  • Odds ratio (OR) = one odds divided by the other = 2.022 (1.08–3.78)

Same table, same people, and the OR comes out about 26% larger than the RR. Read that OR aloud as “the risk doubled” and you have overstated the effect. What actually happened is that the risk went from 25.2% to 40.5%.

A curve plot. The horizontal axis is the unexposed group's risk in per cent; the vertical axis is the risk ratio implied by a fixed odds ratio. The curve falls from upper left to lower right, hugging the dashed horizontal line at OR = 2.02 when risk is low and pulling away from it as risk rises. A filled point marks this page's data: unexposed risk 25.2% with a risk ratio of 1.61, labelled birthwt: RR = 1.61. A vertical dashed line marks the overall low-birth-weight prevalence of 31.2%.
The OR is held fixed and only the unexposed group's baseline risk changes. When the outcome is rare, RR is nearly equal to OR; when the outcome is common, the OR is always further from 1 than the RR. The example on this page sits at the marked point.Plotting script figures/scripts/B2-02-logistic.R

This is algebra, not coincidence. Given an OR and an unexposed risk p0p_0, the exposed risk is

p1=ORp0/(1p0)1+ORp0/(1p0)RR=p1p0p_1 = \frac{\mathrm{OR} \cdot p_0 / (1-p_0)}{1 + \mathrm{OR} \cdot p_0 / (1-p_0)} \quad\Longrightarrow\quad \mathrm{RR} = \frac{p_1}{p_0}

Holding this page’s OR fixed and varying the baseline risk:

Risk in the unexposedRR implied by this OR
1%2.001
5%1.924
20%1.679
40%1.435

The adjusted OR

A forest plot of adjusted odds ratios with 95% confidence intervals for eight variables. Five intervals do not cross 1: smoking, Black race, history of hypertension and previous preterm labour all have odds ratios above 1, with their whole line to the right of the dashed reference line; the mother's weight has an odds ratio of 0.985 with its whole line to the left, the only variable falling below 1. Three intervals cross 1: age, uterine irritability, and Other race.
Adjusted odds ratios from the eight-variable logistic model. The dashed line is OR = 1. An interval crossing that line means this study did not detect an association between that variable and low birth weight.Plotting script figures/scripts/B2-02-logistic.R
VariableAdjusted OR95% CIp
Smoking during pregnancy2.331.048–5.1870.038
Age, per year0.960.894–1.0370.318
Mother's weight, per lb0.990.972–0.9990.034
Race: Black vs White3.361.184–9.5480.023
Race: Other vs White2.230.928–5.3820.073
History of hypertension6.291.585–24.9540.009
Uterine irritability2.040.822–5.0470.125
Previous preterm labour3.391.369–8.4080.008

The OR for smoking moves from a crude 2.022 to an adjusted 2.331.

Most textbooks will tell you the difference is confounding. Half of it is; the other half is not, and the other half is almost never mentioned:

The remaining columns read exactly as in linear regression: an OR on a continuous variable must carry its unit (the OR of 0.963 for age is per year); a variable whose confidence interval crosses 1 should be written up as “this study did not detect an association”, not as “no association”; and the global model test (likelihood ratio 37.8, df = 8, p < 0.001) asks whether all the coefficients are simultaneously 0.

Separation

Sometimes glm() returns a dramatic-looking coefficient attached to an absurd standard error. That is usually not strong evidence; it is separation — some variable splits the outcome perfectly, or nearly perfectly.

This dataset contains a ready-made example, no fabrication needed. Treat the number of previous preterm labours, ptl, as a four-level factor:

Previous preterm laboursNormal weightLow birth weight
011841
1816
232
310

The last row contains 1 mother, and her baby was not low birth weight. That cell is 0, so within these data the level “three previous preterm labours” is synonymous with “low birth weight cannot happen”. The model responds like this:

TermCoefficientSEp
(Intercept)-1.280.23< 0.001
smoke_fYes0.580.340.087
ptl_f11.650.48< 0.001
ptl_f20.520.940.582
ptl_f3-13.86882.740.987

EPV: at least ten events per variable

How many variables a logistic model can carry depends on the number of events, not the sample size. The model on this page has 59 events and 8 parameters, so EPV (events per variable) = 7.38.

Common misuses

MisuseWhy it is wrong
Reading an OR as an RR when the outcome is not rareThe OR is always further from 1, and the gap widens as the outcome becomes more common
Reporting only an OR from a cohort study or RCT that has denominatorsAn RR or risk difference is available directly; the OR demands an extra assumption
Attributing the whole crude-to-adjusted change in an OR to confoundingThe OR is non-collapsible; a conditional OR sits further from 1 by construction
Comparing the size of ORs between two papersDifferent adjustment sets mean the two ORs define different contrasts
Using a model’s OR to compute an NNT or a population-level impactThat needs a marginal estimate (standardisation / G-computation), not a conditional OR
Reporting an OR on a continuous variable without its unitPer year and per decade are entirely different numbers
Reporting a huge OR produced by separationThe estimate does not exist; collapse categories or use Firth
Dismissing fitted probabilities numerically 0 or 1 as noiseIt is usually the only warning of separation you will get
Loading many covariates into a model with few eventsOverfitting; neither the coefficients nor the intervals can be trusted
Choosing variables by looking at significance firstPost-selection p-values and confidence intervals are invalid
Ranking variables by “importance” using the size of their ORsThe scale depends on each variable’s unit and distribution, not on importance
Fitting a matched case-control study with ordinary logistic regressionUse conditional logistic regression; see case-control studies
Describing an effect size when the confidence interval crosses 1Write “no significant association was detected” and give the interval

Reproducing every number on this page

/opt/homebrew/bin/Rscript figures/scripts/B2-02-logistic.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.

Low birth weight is not rare in these data, and the crude odds ratio is 2.02. Can you say smoking doubles the risk?

Show the answer and why

Correct answer: No - the risk ratio is 1.61, and when an outcome is common the OR sits further from one than the RR

The risk ratio is 1.61 against an odds ratio of 2.02, a wide gap because this outcome is anything but rare. The two converge only when events are uncommon; the higher the prevalence the further they separate, and the OR is always the one further from one. Reading an OR as "risk multiplied by" overstates the effect, which is how abstracts routinely phrase it. 3.78 is the OR's upper confidence bound, describing uncertainty rather than a second effect measure.

After adjusting for age, maternal weight and race, smoking's odds ratio moves away from the crude 2.02. What has adjustment done?

Show the answer and why

Correct answer: It becomes 2.33 - adjustment can move an estimate in any direction, and here it moves outward

The adjusted OR is 2.33, further from one than the crude 2.02. "Adjustment pulls estimates towards the null" is a common intuition and it is simply not true: the direction depends on how each covariate relates to the exposure and to the outcome, and an estimate can move outward, inward, or across. 3.36 is the race row of the same model, not smoking's. Faced with a crude and an adjusted figure, the question is which variables entered and why, not which way it should have gone.

30 of the 74 smokers had a low-birth-weight baby. What is the risk in the smoking group?

Show the answer and why

Correct answer: 0.405 - denominator is everyone in that group

Risk divides by everyone, giving 0.405. 0.682 is the same group's odds, whose denominator excludes those who had the event, which is why odds always exceed risk. When events are common the two diverge widely - and logistic regression hands you the odds side, which is why talking about risk from a logistic model requires converting first. 0.252 is the non-smokers' risk, read off the wrong row.

Watch next

StatQuest: Logistic Regression
ENStatQuest with Josh Starmer· 9 minNine minutes to build the intuition — why probability gets converted to log-odds and where the S-shaped curve comes from. Watch before the first section.
Logistic Regression Details Pt1: Coefficients
ENStatQuest with Josh Starmer· 19 minSpecifically on how a coefficient becomes an OR, which is exactly the column the fourth and fifth sections here are reading.
醫學統計 EP14 羅吉斯迴歸
繁中EDMAN MURMURS· 13 minIn Mandarin, from a clinician's point of view. A full episode, useful if you need the Chinese terms alongside the English ones.
醫學統計 EP15 RR vs OR
繁中EDMAN MURMURS· 11 minIn Mandarin. The one episode that tackles the RR-versus-OR difference head on, matching the third section of this page.
【Hands-on】L9 R: Logistic Regression
繁中MeDA School(洪弘)· 45 minIn Mandarin, graduate-level hands-on R. Watch it if you want to type the whole workflow out yourself.

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.