Guides / Cox regression
Cox regression and the hazard ratio
Cox regression adds covariates to survival data and returns a hazard ratio. It is the standard model for time-to-event outcomes, and its central assumption is also the one most often left untested. This guide covers what a hazard ratio actually means, why Cox needs no distribution for survival times, how to test proportional hazards, and what to do when the assumption fails.
The ratio of the instantaneous event rate in one group to the rate in another, among people still event-free at that moment. A hazard ratio of 0.7 means that at any given time, those remaining in the treated group are having events at 70% of the rate of those remaining in the control group. It is not a risk ratio and it is not a measure of how much longer anyone lives. It describes a rate at an instant, averaged across follow-up.
The model
What Cox regression does
Cox models the hazard, the instantaneous rate of the event among those still at risk, as a baseline hazard multiplied by a factor depending on covariates. The clever part is that the baseline hazard is never estimated. It cancels out of the partial likelihood, so you get covariate effects without committing to any shape for how risk changes over time.
That is why Cox is called semi-parametric, and why it is the default rather than a parametric survival model. You rarely know the true shape of a baseline hazard, and Cox does not make you guess.
Because the baseline hazard is never estimated, Cox on its own cannot tell you absolute survival. It gives relative effects. If you need predicted survival at five years you must recover a baseline survival function as a separate step, and that is an extra assumption rather than part of the model output.
Reading the output
Interpreting a hazard ratio
The coefficient is on the log-hazard scale, so the exponentiated coefficient is the hazard ratio. Above 1 means a higher rate of events, below 1 a lower one.
| It is | It is not |
|---|---|
| A ratio of event rates at each instant among survivors | A ratio of risks over the whole period |
| Averaged over the follow-up actually observed | A statement about any particular time point |
| Relative | Informative about absolute benefit on its own |
| Dependent on who remains at risk | A statement about how much longer people live |
The phrase to avoid is "patients lived 30% longer". A hazard ratio of 0.7 says nothing directly about survival time. A large hazard ratio applied to a tiny baseline hazard is still a tiny absolute effect, which is why it should always be reported alongside absolute measures such as survival at fixed time points.
Worked example one
Reading a Cox output table, line by line
A cohort of 410 patients, 78 of whom have the event. Four covariates. This is what the software returns and what each column means.
| Term | coef | SE | HR | 95% CI | z | p |
|---|---|---|---|---|---|---|
| Treatment (vs control) | −0.3567 | 0.1480 | 0.700 | 0.524 to 0.936 | −2.41 | 0.016 |
| Age, per year | 0.0405 | 0.0112 | 1.041 | 1.019 to 1.064 | 3.62 | <0.001 |
| Male (vs female) | 0.2231 | 0.1690 | 1.250 | 0.898 to 1.741 | 1.32 | 0.187 |
| Stage III+ (vs I–II) | 0.7419 | 0.1830 | 2.100 | 1.467 to 3.006 | 4.05 | <0.001 |
Step 1. Where the hazard ratio comes from
The coefficient is on the log-hazard scale. Exponentiate it.
HR = exp(−0.3567) = 0.700
Treated patients are having events at 70% of the rate of controls, among those still event-free at any given moment.
Step 2. Where the interval comes from
Build it on the log scale, then transform back. Never add and subtract on the hazard ratio itself.
exp(−0.3567 ± 1.96 × 0.1480) = exp(−0.647) to exp(−0.067)
= 0.524 to 0.936
It excludes 1, consistent with the p-value of 0.016. The asymmetry around 0.700 is expected and correct: ratios are symmetric on the log scale, not the natural one.
Step 3. Continuous covariates need a sensible unit
Age has a hazard ratio of 1.041, which sounds negligible until you notice it is per single year. Rescale it to something a reader can use.
per 10 years: exp(0.0405 × 10) = exp(0.405) = 1.499, 95% CI 1.20 to 1.87
A decade of age raises the hazard by about half. Same model, same data, far more informative presentation. Scale continuous covariates to a meaningful unit before reporting, and say what the unit is.
Step 4. The non-significant term
Sex has a hazard ratio of 1.25 with an interval from 0.90 to 1.74. That is not evidence of no difference, it is a result compatible with anything from a 10% reduction to a 74% increase. With 78 events the study was never going to settle it, and saying "sex was not associated with outcome" overstates what the data can support.
Step 5. Check the events budget before trusting any of it
78 events / 4 covariates = 19.5 events per variable
Comfortably above the usual minimum of ten. Had the model carried twelve covariates, the same 78 events would give 6.5 per variable and every interval above would be narrower than it should be.
Worked example two
What a proportional hazards failure hides
A surgical intervention carries early operative risk and long-term benefit. Suppose the truth is:
months 0–12: HR = 1.80 (worse)
months 12+: HR = 0.60 (better)
What a single Cox model reports
A single hazard ratio is roughly an average of the log hazard ratios, weighted by how many events fall in each period. With events split evenly, 39 in each:
weighted log HR = (39 × ln 1.80 + 39 × ln 0.60) / 78 = 0.038
overall HR = exp(0.038) ≈ 1.04
The model reports a hazard ratio of 1.04 with an interval comfortably spanning 1, and the paper concludes no effect. In reality the intervention nearly doubled the early hazard and cut the later one by 40%. Both findings matter clinically, and the single number erased both.
Why the answer depends on follow-up length
| Events early / late | Overall HR reported | Conclusion drawn |
|---|---|---|
| 58 / 20 (short follow-up) | 1.36 | "Treatment is harmful" |
| 39 / 39 (balanced) | 1.04 | "No effect" |
| 20 / 58 (long follow-up) | 0.80 | "Treatment is beneficial" |
Same underlying truth, three different published conclusions, decided entirely by how long the study ran. This is why a hazard ratio is described as averaged over the follow-up actually observed, and why that phrase is not a technicality.
What to report instead
Split follow-up at twelve months and give both hazard ratios, each with an interval, stating that the split was chosen because the operative period is clinically distinct rather than because it maximised anything. Add restricted mean survival time at a fixed horizon, which stays interpretable whether or not hazards are proportional.
The assumption
The proportional hazards assumption
Cox assumes the hazard ratio is constant over time. One group may be at higher risk throughout, but the multiple must not change as follow-up proceeds.
Plenty of real situations break this. Surgery carries high early risk and a long-term benefit, so its hazard ratio starts well above 1 and falls below it. A treatment effect that wears off produces a ratio drifting back towards 1. In both cases a single hazard ratio averages opposing effects and can land near 1, reporting "no difference" for an intervention that mattered a great deal at both ends.
If the Kaplan-Meier curves cross, proportional hazards has failed and no amount of testing is needed to tell you so. Reporting a single hazard ratio in that situation is not a judgement call, it is a mistake.
Checking
How to test it
cox.zph in R and estat phtest in Stata.Beware the sample size trap in both directions. With a large sample the Schoenfeld test flags trivial departures; with a small one it misses serious ones. Read the plot as well as the p-value.
Remedies
What to do when it fails
| Approach | When it suits |
|---|---|
| Stratify | The offending variable is a nuisance you want to adjust for but need no estimate of. Each stratum gets its own baseline hazard, and you get no hazard ratio for that variable. |
| Time-varying coefficient | You want to describe how the effect changes. Report separate hazard ratios for defined periods, for example 0 to 1 year and beyond. |
| Split follow-up | There is a natural break, such as a perioperative period. Analyse the intervals separately and say why you chose them. |
| Restricted mean survival time | You want a single number that stays valid without proportional hazards. RMST is the average event-free time up to a horizon, and the difference between groups is directly interpretable. |
| Accelerated failure time model | You are willing to assume a distribution and want effects on survival time rather than hazard. |
Restricted mean survival time is underused and worth knowing about. It answers the question clinicians actually ask, which is how much extra event-free time a treatment buys over a stated period.
Details that matter
Practical matters
Doing it
In R, SPSS and Stata
R
The survival package is the reference implementation and everything else follows its conventions.
library(survival)
fit <- coxph(Surv(time, status) ~ treatment + age + sex + stage, data = df)
summary(fit)
summary() prints coefficients and exponentiated hazard ratios with intervals in one table. Test the assumption with cox.zph(fit), then plot(cox.zph(fit)) to see the residuals against time, which is more informative than the p-value. For a time-varying effect use tt() inside the formula, and for clustered data add + cluster(centre) for robust standard errors or + frailty(centre) for a random effect.
SPSS
Cox regression sits under Analyze, Survival, Cox Regression. The syntax is:
COXREG time /STATUS = status(1)
/METHOD = ENTER treatment age sex stage
/PRINT = CI(95)
/CRITERIA = PIN(.05) POUT(.10).
SPSS reports Exp(B), which is the hazard ratio, with its interval. It has no direct equivalent of cox.zph, so test proportional hazards by adding a time-dependent covariate through Cox Regression with Time-Dependent Covariates, defining an interaction between the variable and T_.
Stata
Declare the survival structure once with stset, then the model needs no time or status arguments.
stset time, failure(status == 1)
stcox treatment age i.sex i.stage
estat phtest, detail
stcox reports hazard ratios by default; add , nohr for coefficients on the log scale. estat phtest, detail gives the Schoenfeld test per covariate and globally. Use , vce(cluster centre) for clustered data and stsplit to create period-specific effects.
Every package needs to know which value of the status variable means the event happened. Coding censoring as 1 and the event as 0 produces a model that runs without complaint and answers the opposite question. Confirm the number of events in the output matches the number you expect before reading anything else.
Avoid these
Six mistakes that cost marks
| Mistake | Why it matters |
|---|---|
| Never testing proportional hazards | The model's central assumption. If it fails, the single hazard ratio can report no effect for an intervention that mattered in both directions. |
| Saying "lived 30% longer" | A hazard ratio of 0.70 is a ratio of event rates, not of survival times. It says nothing directly about how much longer anyone lived. |
| Counting participants instead of events | Power comes from events. Two thousand patients with twelve events supports about one covariate, not twelve. |
| Reporting a per-unit HR for age | 1.041 per year looks trivial and is 1.50 per decade. Rescale to a unit a reader can act on. |
| Treating a wide interval as evidence of no effect | An HR of 1.25 from 0.90 to 1.74 is compatible with meaningful harm. Absence of significance is not absence of effect. |
| Ignoring clustering | Patients within centres, or repeated events per person, break independence. Use a robust variance or a frailty term. |
Writing it up
How to report it
If an analysis is already written up and you want it checked before submission, proportional hazards is one of the first things a reviewer will look for. An independent statistical review covers it.
Common questions
Frequently asked questions
What is a hazard ratio?
The ratio of the instantaneous event rate in one group to that in another, among people still event-free at that moment. A hazard ratio of 0.7 means the treated group is having events at 70% of the rate of the control group at any given time. It is relative, it is averaged across follow-up, and it says nothing directly about how much longer anyone lives.
Is a hazard ratio the same as a risk ratio?
No. A risk ratio compares cumulative probabilities over a whole period. A hazard ratio compares instantaneous rates among those still at risk, which changes as the at-risk groups change. They are similar when the event is rare and follow-up short, and they diverge otherwise.
What is the proportional hazards assumption?
That the hazard ratio between groups stays constant over follow-up. One group may be consistently worse, but the multiple must not change. It fails when a treatment effect wears off, when there is early harm and late benefit, and whenever survival curves cross.
How do I test proportional hazards?
Scaled Schoenfeld residuals are the standard approach, plotted against time and tested for a trend. Log-minus-log plots should show parallel lines. Adding an interaction between the covariate and time tests it directly. Inspect the plots as well as the p-values, since the test is over-sensitive in large samples and under-sensitive in small ones.
What if the assumption fails?
Stratify on the offending variable if you do not need an estimate for it, fit a time-varying coefficient and report separate hazard ratios by period, split follow-up at a natural break, or switch to restricted mean survival time, which stays interpretable without the assumption.
How many events do I need?
Events drive power, not participants. A widely used rule is at least ten events per covariate, so a study with twelve events can support about one variable regardless of how many people were enrolled. Fitting more produces unstable estimates and overly narrow intervals.
Keep reading