Why Do Logistic and Conditional Logistic Regression Give Different Odds Ratios?

On this page
อ่านฉบับภาษาไทย (Thai version)
Abstract
Ordinary and conditional logistic regression can give very different odds ratios from the same data, because they answer different questions. In 20 matched pairs from a nested case-control study of inadequate antenatal care and neonatal morbidity within 28 days, ordinary logistic regression gives an odds ratio of 1.83 and conditional logistic regression gives 4.00. Each control was drawn by risk-set sampling from newborns still at risk when its case had the outcome, so the design asks a within-set question. Pooling the 40 rows compares all cases with all controls: (12/8)/(9/11) = 1.83. Conditioning on the set leaves only the 5 discordant pairs to inform the exposure: 4/1 = 4.00, so imprecise that its 95% confidence interval runs from 0.45 to 35.79. Under suitable sampling, the matched odds ratio estimates a Cox hazard ratio, not a risk ratio. This article works both estimates by hand, derives the conditional likelihood, links clogit to Cox regression and reproduces both models in Stata.
Same pairs, two odds ratios: 1.83 and 4.00
A neonatal research team wants to know whether inadequate antenatal care (ANC), too few or too late check-ups during pregnancy, is associated with neonatal morbidity within 28 days after birth.
The team has data from 20 matched case-control pairs and analyses them in two ways:
- Ordinary logistic regression gives an odds ratio of 1.83.
- Conditional logistic regression gives an odds ratio of 4.00.
Both models use the same data, the same exposure and the same outcome, yet the results differ clearly.
The key question is why this difference arises, and which result to believe.
Answering it has to start from the study design, not from the statistical equations. The 20 pairs used throughout are a constructed example, built to make the difference between the two models visible. They are not data from any real unit.
The design first: risk-set sampling
Suppose newborns are followed from birth until 28 days of age, and the outcome of interest is the time to the first composite morbidity event, the first of a set of predefined neonatal complications.
When a newborn has the outcome, say on day 5 after birth, that newborn becomes a case.
A control is then drawn at random from the newborns still at risk at the moment the case had the event, that is, from those who have not yet had the outcome. Drawing controls in this way is risk-set sampling, and the newborns still at risk at that moment form the case's risk set [1]. A separate post on control sampling compares this scheme with others.
For example, one case and its control might look like this:
| Case | Control | |
|---|---|---|
| Newborn | A | B |
| ANC | Inadequate | Adequate |
| Status on day 5 | Has the outcome | Has not yet had the outcome |
| Risk set | 1 | 1 |
How a matched pair is built
This example uses 1:1 matching:
- each risk set has 1 case;
- it has 1 control sampled for that case;
- both rows of the pair carry the same
set_id, the identifier of the matched set.
So 20 matched pairs make 40 observation rows in the dataset. In a real study these need not be 40 different newborns, because one newborn can appear in several risk sets.
The example dataset: 20 matched pairs
To show the difference between the models, the example uses 20 constructed matched pairs, counted by the ANC of the case and the ANC of its control.
| Case's ANC | Control's ANC | Number of pairs |
|---|---|---|
| Inadequate | Inadequate | 8 |
| Adequate | Adequate | 7 |
| Inadequate | Adequate | 4 |
| Adequate | Inadequate | 1 |
| Total | 20 |
Concordant and discordant pairs
Check the number of pairs: 8 + 7 + 4 + 1 = 20 pairs.
Every pair always holds one case and one control, so the data hold 20 cases and 20 controls.
Notice that the pairs fall into two kinds.
Concordant pairs (15 pairs) are pairs in which case and control have the same ANC:
- 8 pairs: both the case and the control had inadequate ANC.
- 7 pairs: both the case and the control had adequate ANC.
Discordant pairs (5 pairs) are pairs in which the ANC differs:
- 4 pairs: the case had inadequate ANC, but the control had adequate ANC.
- 1 pair: the case had adequate ANC, but the control had inadequate ANC.
Ordinary logistic regression: ignoring the matching
Ordinary logistic regression does not use the information on which case was matched with which control.
The software sees the data as 20 cases and 20 controls and counts them into a 2 × 2 table.
| ANC | Case | Control |
|---|---|---|
| Inadequate | 12 | 9 |
| Adequate | 8 | 11 |
| Total | 20 | 20 |
Step by step: the ordinary odds ratio
Each cell of the table comes from the pair table:
- Cases with inadequate ANC = 8 + 4 = 12
- Cases with adequate ANC = 7 + 1 = 8
- Controls with inadequate ANC = 8 + 1 = 9
- Controls with adequate ANC = 7 + 4 = 11
-
Step 1. Exposure odds among cases
\[ \text{Odds among cases} = \frac{12}{8} = 1.50 \]
Of the 20 cases, 12 had inadequate ANC and 8 had adequate ANC; this is the odds of inadequate ANC among the cases.
-
Step 2. Exposure odds among controls
\[ \text{Odds among controls} = \frac{9}{11} = 0.818 \]
Of the 20 controls, 9 had inadequate ANC and 11 had adequate ANC; this is the odds of inadequate ANC among the controls.
-
Step 3. The ordinary odds ratio
\[ \mathrm{OR} = \frac{12/8}{9/11} = \frac{1.50}{0.818} = 1.83 \]
Divide the odds of the two groups.
Result: Ordinary logistic regression gives OR = 1.83: the odds of inadequate ANC among the cases are about 1.83 times those among the controls, when the analysis pools the pairs without using the matching.
This analysis, however, ignores the risk sets fixed by the sampling, so it does not compare the people within the same risk set, as the study design requires.
Conditional logistic regression: preserving the matched sets
Conditional logistic regression asks a different question.
Why concordant pairs do not help estimate the ANC effect
Consider the following pair.
| Case | Control | |
|---|---|---|
| ANC | Inadequate | Inadequate |
What the discordant pairs tell us
Look only at the 5 pairs in which ANC differs.
| Case's ANC | Control's ANC | Number of pairs |
|---|---|---|
| Inadequate | Adequate | 4 |
| Adequate | Inadequate | 1 |
| Total | 5 |
Why conditional logistic regression works this way
What matters is not only remembering the formula 4/1 but understanding why the conditional likelihood leads to it.
Suppose each matched pair holds exactly one case. Conditional logistic regression considers the probability that a given member of the pair is the case, given that the outcome occurred once in that pair. Read as a function of the coefficient, the probability of the observed cases under that condition is the conditional likelihood [2].
Let $X = 1$ mean inadequate ANC and $X = 0$ adequate ANC, let $\beta$ be the regression coefficient of ANC, and let $\exp(\beta)$ be the conditional odds ratio.
-
The newborn with inadequate ANC is the case
\[ P = \frac{\exp(\beta)}{1 + \exp(\beta)} \]
In a pair whose members differ in ANC, this is the model probability that the newborn with inadequate ANC is the case.
-
The newborn with adequate ANC is the case
\[ 1 - P = \frac{1}{1 + \exp(\beta)} \]
The probability that, instead, the newborn with adequate ANC is the case.
-
The conditional likelihood
\[ L(\beta) \propto P^{4}\,(1 - P)^{1} \]
The data show the first pattern in 4 pairs and the second in 1 pair, so the part of the conditional likelihood that depends on ANC is proportional to this product.
-
The maximum
\[ P = \frac{4}{5} = 0.80 \]
This is the value of $P$ that makes the likelihood largest.
-
Back to the odds ratio
\[ \exp(\beta) = \frac{P}{1 - P} = \frac{0.80}{0.20} = 4.00 \]
This is the mathematical reason conditional logistic regression gives OR = 4.00.
-
The concordant pairs
\[ P_{\text{concordant}} = \frac{1}{2} \]
For a concordant pair, whatever the value of $\beta$, the conditional probability of the observed pattern is 1/2, so these pairs do not help identify $\beta$ in this one-variable model.
Result: In other words, the conditional likelihood uses the differences within each pair, not only the difference in the number exposed between all cases and all controls. Here it gives OR = 4.00.
Comparing the two models
| Feature | Ordinary logistic | Conditional logistic |
|---|---|---|
| Data | 20 matched pairs | 20 matched pairs |
| Observation rows | 40 | 40 |
Uses set_id | No | Yes |
| Comparison | Pooled cases against controls | Within matched sets |
| Estimation | Unconditional likelihood | Conditional likelihood |
| OR in the example | 1.83 | 4.00 |
| Supports this design directly | Not in the form that ignores the matching | Yes |
What the difference does and does not mean
This difference does not mean that ordinary logistic regression is always the wrong model.
But using ordinary logistic regression without regard to the matched risk sets may estimate an effect that does not match the study design, and it may introduce bias.
Nor does the conditional odds ratio exceed the ordinary one in every study. The difference depends on the structure of the data, the matching, confounding and the properties of the odds ratio itself, such as non-collapsibility: an odds ratio within subgroups can differ from one averaged over them even without confounding [3]. The part of this series on conditional and marginal odds ratios works through that property.
Advanced: how clogit is related to Cox regression
In a study with concurrent, or incidence-density, sampling, controls are drawn from the people still in the risk set at the time the case has the outcome.
The hazard is the instantaneous event rate at time $t$ among those still free of the event. Under the Cox proportional hazards model,
$$h(t \mid X) = h_0(t) \times \exp(\beta X)$$where $h_0(t)$ is the baseline hazard at time $t$ and $\exp(\beta X)$ is the relative hazard of a person with exposure $X$.
If one event occurs at time $t$, the case's term in the Cox partial likelihood has the form
$$\text{Likelihood} = \frac{\text{relative hazard of the case}}{\text{sum of the relative hazards of everyone in the risk set}}$$Conditional logistic regression uses a likelihood of the same structure, but it compares the case with the controls sampled into the matched risk set. In a 1:1 pair that risk set holds only the case and its control, which is why the probability $P$ above has the form it has.
For this reason, under suitable sampling and assumptions, $\exp(\beta)$ from conditional logistic regression can estimate the hazard ratio, the ratio of two hazards, that a Cox model targets in the full cohort.
If the hazard ratio is constant over follow-up, and both the sampling of controls and the analysis are aligned with event time, the estimate can be read as a relative hazard or an instantaneous incidence rate ratio, without relying on the rare disease assumption, the assumption that the outcome is rare enough for an odds ratio to approximate a risk ratio [4].
Stata: the same pairs as a stratified Cox model
* the same likelihood as a Cox model stratified by matched set: the case has its event at time 1 and its
* control is censored at time 2, so each risk set holds exactly the pair
generate byte t = 2 - case
stset t, failure(case)
stcox i.inadequate_anc, strata(set_id) nolog
. * the same likelihood as a Cox model stratified by matched set: the case has its event at time 1 and its
. * control is censored at time 2, so each risk set holds exactly the pair
. generate byte t = 2 - case
. stset t, failure(case)
Survival-time data settings
Failure event: case!=0 & case<.
Observed time interval: (0, t]
Exit on or before: failure
--------------------------------------------------------------------------
40 total observations
0 exclusions
--------------------------------------------------------------------------
40 observations remaining, representing
20 failures in single-record/single-failure data
60 total analysis time at risk and under observation
At risk from t = 0
Earliest observed entry t = 0
Last observed exit t = 2
. stcox i.inadequate_anc, strata(set_id) nolog
Failure _d: case
Analysis time _t: t
Stratified Cox regression with no ties
Strata variable: set_id
No. of subjects = 40 Number of obs = 40
No. of failures = 20
Time at risk = 60
LR chi2(1) = 1.93
Log likelihood = -12.89922 Prob > chi2 = 0.1650
----------------------------------------------------------------------------------
_t | Haz. ratio Std. err. z P>|z| [95% conf. interval]
-----------------+----------------------------------------------------------------
1.inadequate_anc | 4 4.472136 1.24 0.215 .4470826 35.78757
----------------------------------------------------------------------------------
| Effect measure | Meaning |
|---|---|
| Odds ratio (OR) | A ratio of odds |
| Risk ratio (RR) | A ratio of cumulative risks over a stated period |
| Incidence rate ratio (IRR) | A ratio of event rates per person-time |
| Hazard ratio (HR) | A ratio of instantaneous hazards at a given time |
What conditional logistic regression does not do
Conditional logistic regression does not turn an odds ratio into a risk ratio automatically.
Reading an odds ratio from risk-set sampling as a hazard ratio or a rate ratio depends on conditions of the design, the sampling and the hazard model, in particular matching on event time and the assumptions about how the effect changes over time [5].
If the hazard ratio changes over time, the model's estimate may reflect an average of the effect weighted by the events, rather than one constant hazard ratio that describes every period.
Reproduce the example in Stata
The example can be built without any external dataset. These are the hand example's commands:
clear
* Four patterns of matched pairs
input byte anc_case anc_ctrl n_pairs
1 1 8
0 0 7
1 0 4
0 1 1
end
* Create 20 matched sets
expand n_pairs
gen long set_id = _n
* Reshape to one row per observation
reshape long anc_, i(set_id) j(role) string
rename anc_ inadequate_anc
* Case indicator
gen byte case = (role == "case")
* Check the matched-set structure
bysort set_id: assert _N == 2
bysort set_id: assert case[1] != case[2]
* Pooled 2x2 table
tab inadequate_anc case
* Ordinary logistic regression
logistic case i.inadequate_anc
* Conditional logistic regression
clogit case i.inadequate_anc, ///
group(set_id) orStata documents the clogit command in its reference manual [6], and a Stata FAQ explains why clogit omits a covariate that does not vary within the matched sets [7].
| Model | Expected OR |
|---|---|
logistic | 1.83 |
clogit | 4.00 |
The set_id in a real study, and the runs
In a real study, use the set_id created at the step that sampled the risk-set controls, not a new set ID made by pairing people at random after the data are in.
The panes below run the same steps with the simulation script behind this series, in Stata and then in R, beside the output each printed. Ordinary logistic regression returns 1.83 and conditional logistic regression returns 4.00, as the hand calculation expects.
Stata: entering the 20 pairs
clear
input byte anc_case byte anc_ctrl int n_pairs
1 1 8
0 0 7
1 0 4
0 1 1
end
quietly summarize n_pairs
canon pairs.n 0 r(sum)
quietly summarize n_pairs if anc_case == anc_ctrl
canon pairs.concordant 0 r(sum)
quietly summarize n_pairs if anc_case != anc_ctrl
canon pairs.discordant 0 r(sum)
quietly summarize n_pairs if anc_case == 1 & anc_ctrl == 0
canon pairs.case_only_inadequate 0 r(sum)
quietly summarize n_pairs if anc_case == 0 & anc_ctrl == 1
canon pairs.control_only_inadequate 0 r(sum)
expand n_pairs
drop n_pairs
generate int set_id = _n
reshape long anc_, i(set_id) j(role) string
rename anc_ inadequate_anc
generate byte case = role == "case"
bysort set_id: assert _N == 2
bysort set_id (case): assert case[1] == 0 & case[2] == 1
quietly count
canon pairs.rows 0 r(N)
* the pooled 2 x 2 table that ordinary logistic regression sees
tabulate inadequate_anc case
. clear
. input byte anc_case byte anc_ctrl int n_pairs
anc_case anc_ctrl n_pairs
1. 1 1 8
2. 0 0 7
3. 1 0 4
4. 0 1 1
5. end
. quietly summarize n_pairs
. canon pairs.n 0 r(sum)
CANON c7.pairs.n 20
. quietly summarize n_pairs if anc_case == anc_ctrl
. canon pairs.concordant 0 r(sum)
CANON c7.pairs.concordant 15
. quietly summarize n_pairs if anc_case != anc_ctrl
. canon pairs.discordant 0 r(sum)
CANON c7.pairs.discordant 5
. quietly summarize n_pairs if anc_case == 1 & anc_ctrl == 0
. canon pairs.case_only_inadequate 0 r(sum)
CANON c7.pairs.case_only_inadequate 4
. quietly summarize n_pairs if anc_case == 0 & anc_ctrl == 1
. canon pairs.control_only_inadequate 0 r(sum)
CANON c7.pairs.control_only_inadequate 1
. expand n_pairs
(16 observations created)
. drop n_pairs
. generate int set_id = _n
. reshape long anc_, i(set_id) j(role) string
(j = case ctrl)
Data Wide -> Long
-----------------------------------------------------------------------------
Number of observations 20 -> 40
Number of variables 3 -> 3
j variable (2 values) -> role
xij variables:
anc_case anc_ctrl -> anc_
-----------------------------------------------------------------------------
. rename anc_ inadequate_anc
. generate byte case = role == "case"
. bysort set_id: assert _N == 2
. bysort set_id (case): assert case[1] == 0 & case[2] == 1
. quietly count
. canon pairs.rows 0 r(N)
CANON c7.pairs.rows 40
. * the pooled 2 x 2 table that ordinary logistic regression sees
. tabulate inadequate_anc case
inadequate | case
_anc | 0 1 | Total
-----------+----------------------+----------
0 | 11 8 | 19
1 | 9 12 | 21
-----------+----------------------+----------
Total | 20 20 | 40
Stata: ordinary logistic regression on the pairs
* ordinary logistic regression ignores the matched sets
logistic case i.inadequate_anc, nolog
. * ordinary logistic regression ignores the matched sets
. logistic case i.inadequate_anc, nolog
Logistic regression Number of obs = 40
LR chi2(1) = 0.91
Prob > chi2 = 0.3413
Log likelihood = -27.27303 Pseudo R2 = 0.0163
----------------------------------------------------------------------------------
case | Odds ratio Std. err. z P>|z| [95% conf. interval]
-----------------+----------------------------------------------------------------
1.inadequate_anc | 1.833333 1.174412 0.95 0.344 .522362 6.434448
_cons | .7272727 .3379347 -0.69 0.493 .292535 1.808076
----------------------------------------------------------------------------------
Note: _cons estimates baseline odds.
Stata: the pooled fit with a cluster-robust standard error
* clustering the standard error on the matched set changes the interval, not the odds ratio
logistic case i.inadequate_anc, vce(cluster set_id) nolog
. * clustering the standard error on the matched set changes the interval, not the odds ratio
. logistic case i.inadequate_anc, vce(cluster set_id) nolog
Logistic regression Number of obs = 40
Wald chi2(1) = 1.82
Prob > chi2 = 0.1770
Log pseudolikelihood = -27.27303 Pseudo R2 = 0.0163
(Std. err. adjusted for 20 clusters in set_id)
----------------------------------------------------------------------------------
| Robust
case | Odds ratio std. err. z P>|z| [95% conf. interval]
-----------------+----------------------------------------------------------------
1.inadequate_anc | 1.833333 .823118 1.35 0.177 .7604568 4.419858
_cons | .7272727 .1778604 -1.30 0.193 .4503282 1.174534
----------------------------------------------------------------------------------
Note: _cons estimates baseline odds.
Stata: conditional logistic regression on the pairs
* conditional logistic regression compares the case with its own control inside each matched set
clogit case i.inadequate_anc, group(set_id) or nolog
. * conditional logistic regression compares the case with its own control inside each matched set
. clogit case i.inadequate_anc, group(set_id) or nolog
Conditional (fixed-effects) logistic regression Number of obs = 40
LR chi2(1) = 1.93
Prob > chi2 = 0.1650
Log likelihood = -12.89922 Pseudo R2 = 0.0695
----------------------------------------------------------------------------------
case | Odds ratio Std. err. z P>|z| [95% conf. interval]
-----------------+----------------------------------------------------------------
1.inadequate_anc | 4 4.472136 1.24 0.215 .4470826 35.78757
----------------------------------------------------------------------------------
R: the pairs and the ordinary logistic fit
pairs <- data.frame(anc_case = c(1, 0, 1, 0), anc_ctrl = c(1, 0, 0, 1), n_pairs = c(8, 7, 4, 1))
canon("pairs.n", sum(pairs$n_pairs), 0)
canon("pairs.concordant", sum(pairs$n_pairs[pairs$anc_case == pairs$anc_ctrl]), 0)
canon("pairs.discordant", sum(pairs$n_pairs[pairs$anc_case != pairs$anc_ctrl]), 0)
canon("pairs.case_only_inadequate", sum(pairs$n_pairs[pairs$anc_case == 1 & pairs$anc_ctrl == 0]), 0)
canon("pairs.control_only_inadequate", sum(pairs$n_pairs[pairs$anc_case == 0 & pairs$anc_ctrl == 1]), 0)
pp <- pairs[rep(seq_len(nrow(pairs)), pairs$n_pairs), ]
pp$set_id <- seq_len(nrow(pp))
m <- rbind(data.frame(set_id = pp$set_id, case = 1L, inadequate_anc = pp$anc_case),
data.frame(set_id = pp$set_id, case = 0L, inadequate_anc = pp$anc_ctrl))
m <- m[order(m$set_id, m$case), ]
stopifnot(all(table(m$set_id) == 2), all(tapply(m$case, m$set_id, sum) == 1))
canon("pairs.rows", nrow(m), 0)
# the pooled 2 x 2 table that ordinary logistic regression sees
print(table(inadequate_anc = m$inadequate_anc, case = m$case))
a <- sum(m$case == 1 & m$inadequate_anc == 1)
bb <- sum(m$case == 1 & m$inadequate_anc == 0)
cc <- sum(m$case == 0 & m$inadequate_anc == 1)
dd <- sum(m$case == 0 & m$inadequate_anc == 0)
canon("pooled.cases_inadequate", a, 0)
canon("pooled.cases_adequate", bb, 0)
canon("pooled.controls_inadequate", cc, 0)
canon("pooled.controls_adequate", dd, 0)
canon("pooled.odds_cases", a / bb)
canon("pooled.odds_controls", cc / dd)
# ordinary logistic regression ignores the matched sets
fp <- glm(case ~ inadequate_anc, family = binomial, data = m)
print(summary(fp)$coefficients)
bp <- coef(fp)[["inadequate_anc"]]
sp <- sqrt(vcov(fp)["inadequate_anc", "inadequate_anc"])
canon("pooled.or", exp(bp))
canon("pooled.se", sp)
canon("pooled.or_lb", exp(bp - z * sp))
canon("pooled.or_ub", exp(bp + z * sp))
> pairs <- data.frame(anc_case = c(1, 0, 1, 0), anc_ctrl = c(1,
+ 0, 0, 1), n_pairs = c(8, 7, 4, 1))
> canon("pairs.n", sum(pairs$n_pairs), 0)
CANON c7.pairs.n 20
> canon("pairs.concordant", sum(pairs$n_pairs[pairs$anc_case ==
+ pairs$anc_ctrl]), 0)
CANON c7.pairs.concordant 15
> canon("pairs.discordant", sum(pairs$n_pairs[pairs$anc_case !=
+ pairs$anc_ctrl]), 0)
CANON c7.pairs.discordant 5
> canon("pairs.case_only_inadequate", sum(pairs$n_pairs[pairs$anc_case ==
+ 1 & pairs$anc_ctrl == 0]), 0)
CANON c7.pairs.case_only_inadequate 4
> canon("pairs.control_only_inadequate", sum(pairs$n_pairs[pairs$anc_case ==
+ 0 & pairs$anc_ctrl == 1]), 0)
CANON c7.pairs.control_only_inadequate 1
> pp <- pairs[rep(seq_len(nrow(pairs)), pairs$n_pairs),
+ ]
> pp$set_id <- seq_len(nrow(pp))
> m <- rbind(data.frame(set_id = pp$set_id, case = 1,
+ inadequate_anc = pp$anc_case), data.frame(set_id = pp$set_id,
+ case = 0, inadequate_anc = pp$anc_ctrl))
> m <- m[order(m$set_id, m$case), ]
> stopifnot(all(table(m$set_id) == 2), all(tapply(m$case,
+ m$set_id, sum) == 1))
> canon("pairs.rows", nrow(m), 0)
CANON c7.pairs.rows 40
> print(table(inadequate_anc = m$inadequate_anc, case = m$case))
case
inadequate_anc 0 1
0 11 8
1 9 12
> a <- sum(m$case == 1 & m$inadequate_anc == 1)
> bb <- sum(m$case == 1 & m$inadequate_anc == 0)
> cc <- sum(m$case == 0 & m$inadequate_anc == 1)
> dd <- sum(m$case == 0 & m$inadequate_anc == 0)
> canon("pooled.cases_inadequate", a, 0)
CANON c7.pooled.cases_inadequate 12
> canon("pooled.cases_adequate", bb, 0)
CANON c7.pooled.cases_adequate 8
> canon("pooled.controls_inadequate", cc, 0)
CANON c7.pooled.controls_inadequate 9
> canon("pooled.controls_adequate", dd, 0)
CANON c7.pooled.controls_adequate 11
> canon("pooled.odds_cases", a/bb)
CANON c7.pooled.odds_cases 1.5000
> canon("pooled.odds_controls", cc/dd)
CANON c7.pooled.odds_controls 0.8182
> fp <- glm(case ~ inadequate_anc, family = binomial,
+ data = m)
> print(summary(fp)$coefficients)
Estimate Std. Error z value Pr(>|z|)
(Intercept) -0.3184537 0.4646602 -0.6853476 0.4931246
inadequate_anc 0.6061358 0.6405884 0.9462172 0.3440378
> bp <- coef(fp)[["inadequate_anc"]]
> sp <- sqrt(vcov(fp)["inadequate_anc", "inadequate_anc"])
> canon("pooled.or", exp(bp))
CANON c7.pooled.or 1.8333
> canon("pooled.se", sp)
CANON c7.pooled.se 0.6406
> canon("pooled.or_lb", exp(bp - z * sp))
CANON c7.pooled.or_lb 0.5224
> canon("pooled.or_ub", exp(bp + z * sp))
CANON c7.pooled.or_ub 6.4344
R: clogit() on the pairs
# conditional logistic regression compares the case with its own control inside each matched set
fc <- clogit(case ~ inadequate_anc + strata(set_id), data = m)
print(summary(fc))
> fc <- clogit(case ~ inadequate_anc + strata(set_id),
+ data = m)
> print(summary(fc))
Call:
coxph(formula = Surv(rep(1, 40L), case) ~ inadequate_anc + strata(set_id),
data = m, method = "exact")
n= 40, number of events= 20
coef exp(coef) se(coef) z Pr(>|z|)
inadequate_anc 1.386 4.000 1.118 1.24 0.215
exp(coef) exp(-coef) lower .95 upper .95
inadequate_anc 4 0.25 0.4471 35.79
Concordance= 0.575 (se = 0.075 )
Likelihood ratio test= 1.93 on 1 df, p=0.2
Wald test = 1.54 on 1 df, p=0.2
Score (logrank) test = 1.8 on 1 df, p=0.2
Common misconceptions
-
"clogit automatically matches cases and controls."
Not true. clogit uses the matched sets that the researcher has already defined through group(set_id); it does not do the matching itself.
Fix: Build the set identifier when the risk-set controls are sampled, and pass it to clogit with group(set_id).
-
"clogit uses only the five discordant pairs and discards the rest."
Not correct in the general sense. The model uses the conditional likelihood of all the matched sets. In this example, with one binary ANC variable, the 15 concordant pairs simply carry no information about the ANC coefficient.
Fix: Keep every matched set in the data, and report how many sets are discordant on the exposure, since they carry its information.
-
"A larger odds ratio means the model is more accurate."
Not true. OR = 4.00 does not prove that the model is more accurate than OR = 1.83. Here the larger estimate also has the far wider interval, 0.45 to 35.79 against 0.52 to 6.43.
Fix: Choose the model from the study design, the estimand, the model assumptions and the risk of bias, never from the size of the odds ratio.
-
"Risk-set sampling always makes the odds ratio equal to the risk ratio."
Not true. This kind of sampling lets the matched odds ratio estimate a relative hazard or a rate ratio under suitable conditions, but it does not automatically equal the 28-day cumulative risk ratio.
Fix: Name the effect measure that the design and its assumptions support, and do not report a matched odds ratio as a risk ratio.
-
"Using robust standard errors fixes ignored matching."
Not true. Robust or cluster-robust standard errors change how the uncertainty of the coefficient is estimated, but they do not turn the point estimate of ordinary logistic regression into a conditional estimate. Clustered on the pair, the pooled odds ratio stays at 1.83; only its 95% interval moves, from 0.52 to 6.43 to 0.76 to 4.42.
Fix: Analyse risk-set matched data with conditional logistic regression; a different standard error changes the interval, never the estimate or the question it answers.
Conclusion
Ordinary logistic regression and conditional logistic regression can give very different odds ratios even from the same data, because their likelihoods and their comparison structures differ.
In this example:
- ordinary logistic regression gives OR = 1.83, from the exposure odds of the cases against the controls, pooled;
- conditional logistic regression gives OR = 4.00, from comparing exposure within the matched sets.
For a nested case-control study with incidence-density sampling, conditional logistic regression is the standard analysis for preserving the matched risk-set structure of the sampling.
To read the estimate as a hazard ratio, the assumptions of the hazard model and the sampling process must also be considered.
Glossary
- risk-set sampling (การสุ่มกลุ่มควบคุมจากกลุ่มเสี่ยง)
- Drawing each case's controls from the people still at risk at the moment the case has the event.
- risk set
- The people still at risk of the outcome at the moment a case has its event.
- nested case-control study (การศึกษาแบบ nested case-control)
- A case-control study drawn from a defined cohort, with controls sampled from those at risk.
- incidence-density sampling (การเลือกกลุ่มควบคุมตามความหนาแน่นของอุบัติการณ์)
- Another name for risk-set sampling: controls drawn from the people still at risk at each case's event time.
- matched set (ชุดที่จับคู่)
- One case together with the controls drawn for it, sharing one set identifier; a pair in 1:1 matching.
- concordant pair (คู่ที่สอดคล้องกัน)
- A matched pair in which case and control share the same exposure; with one binary exposure it carries no information about the exposure in conditional logistic regression.
- discordant pair (คู่ที่ไม่สอดคล้องกัน)
- A matched pair in which case and control differ in exposure; with 1:1 matching, one binary exposure and no other covariates, the matched odds ratio is the ratio of the two kinds.
- conditional likelihood
- The probability of which member of a matched set is the case, given that the set holds exactly one case, read as a function of the coefficients.
- conditional logistic regression
- A logistic model fitted through the conditional likelihood, so that each case is compared only with the members of its own matched set.
- non-collapsibility (ความไม่ยุบรวมได้)
- The property of the odds ratio and the hazard ratio whereby a value averaged over subgroups can differ from the common value within them without any confounding.
- hazard (ฮาซาร์ด)
- The instantaneous event rate at time t among the people still at risk.
- partial likelihood
- The Cox model's likelihood: for each event, the relative hazard of the person with the event over the sum of the relative hazards of everyone in the risk set.
- hazard ratio (อัตราส่วนฮาซาร์ด)
- The ratio of instantaneous event rates between groups, which is not a ratio of risks.
- rare disease assumption
- The assumption that the outcome is rare enough for an odds ratio to approximate a risk ratio; risk-set sampling does not need it for a hazard-ratio reading.
- cluster-robust standard error
- A standard error that allows observations within a cluster, such as a matched pair, to be correlated; it changes the interval, not the estimate.
References
- Langholz B, Goldstein L. Risk set sampling in epidemiologic cohort studies. Stat Sci. 1996;11(1):35-53. doi:10.1214/ss/1032209663 https://doi.org/10.1214/ss/1032209663
- Breslow NE, Day NE. Statistical Methods in Cancer Research, Volume I: The Analysis of Case-Control Studies. IARC Scientific Publications No. 32. Lyon: International Agency for Research on Cancer; 1980. https://publications.iarc.who.int/Book-And-Report-Series/Iarc-Scientific-Publications/Statistical-Methods-In-Cancer-Research-Volume-I-The-Analysis-Of-Case-Control-Studies-1980
- Greenland S, Pearl J, Robins JM. Confounding and collapsibility in causal inference. Stat Sci. 1999;14(1):29-46. doi:10.1214/ss/1009211805 https://doi.org/10.1214/ss/1009211805
- Greenland S, Thomas DC. On the need for the rare disease assumption in case-control studies. Am J Epidemiol. 1982;116(3):547-553. doi:10.1093/oxfordjournals.aje.a113439 https://doi.org/10.1093/oxfordjournals.aje.a113439
- Kerr S, Greenland S, Jeffrey K, et al. Understanding and reporting odds ratios as rate-ratio estimates in case-control studies. J Glob Health. 2023;13:04101. doi:10.7189/jogh.13.04101 https://doi.org/10.7189/jogh.13.04101
- StataCorp. Stata Base Reference Manual: [R] clogit. Stata documentation (PDF) at stata.com. Accessed 11 October 2026. https://www.stata.com/manuals/rclogit.pdf
- Gould W. Within group collinearity in conditional logistic regression. Stata FAQ, StataCorp. Accessed 17 October 2026. https://www.stata.com/support/faqs/statistics/within-group-collinearity-and-clogit/
Key takeaways
- An estimator cannot be read apart from the study design: the same 20 matched pairs give 1.83 from ordinary logistic regression and 4.00 from conditional logistic regression, because the two models answer different questions.
- With risk-set sampling, each control comes from the newborns still at risk when its case has the outcome; a control may become a case later, and the matched set is the unit of comparison.
- Pooling gives (12/8)/(9/11) = 1.50/0.818 = 1.83; conditioning on the matched set leaves the discordant pairs, 4/1 = 4.00, where the conditional likelihood P to the power 4 times (1 - P) peaks at P = 0.80.
- Under suitable sampling and assumptions the matched odds ratio estimates a Cox hazard ratio, not a risk ratio, and it need not equal a full-cohort Cox estimate exactly.
- With only 5 discordant pairs, report 4.00 with its 95% confidence interval, 0.45 to 35.79; a robust standard error does not turn the pooled estimate into a matched one.
Related in the wiki: [[conditional-vs-marginal-or]] [[case-control-sampling-schemes-stata-and-r]] [[conditional-logistic-regression]]