Statistical Tests Open Access

Cox Proportional Hazards Test

Diagram of two survival curves for different covariate groups with a constant hazard ratio between them over time, illustrating the proportional hazards assumption that the Cox model relies on.
Figure 1. The Cox Proportional Hazards Test models how a subject's instantaneous risk of an event depends on covariates, assuming the ratio of hazards between any two subjects stays constant over time.

Introduction

The Cox Proportional Hazards Test checks whether one or more covariates significantly change a subject's instantaneous risk of an event-death, disease relapse, machine failure, loan default, customer churn-while correctly handling censored subjects, the ones who hadn't experienced the event by the time the study ended. If you've ever needed to know whether a treatment lowers the risk of relapse, whether a machine's age raises its failure risk, or whether a subscription plan predicts churn timing, this is usually the test you reach for.

By the end of this article you will be able to state exactly when a Cox Proportional Hazards Model applies, compute a hazard ratio completely by hand on two worked examples, understand what partial likelihood is and why censoring doesn't break the model, know how to check the proportional hazards assumption the entire method depends on, and fit the same model in a few lines of Python with lifelines.

What Is the Cox Proportional Hazards Test?

Introduced by Sir David Cox in 1972, the Cox Proportional Hazards Model is the workhorse of survival analysis-the branch of statistics built around "time-to-event" data, where the outcome isn't just whether something happened, but when. Rather than modeling survival time directly, the model works with the hazard function, \( h(t) \): the instantaneous risk of the event occurring at time \( t \), given that the subject has survived up to that point.

The model's defining move is to leave the baseline hazard \( h_0(t) \)-how risk naturally rises and falls over time for everyone-completely unspecified, and instead only model how covariates multiply that baseline risk up or down. This semi-parametric design is why the Cox model became the default choice for survival data: you get interpretable, covariate-driven risk estimates without ever having to guess the shape of the underlying hazard curve.

Core idea in one line: instead of modeling survival time directly, model how much each covariate multiplies an unspecified baseline risk of the event-holding that multiplier, the hazard ratio, constant over the entire follow-up period.

When to Use It

Use a Cox Proportional Hazards Model whenever your outcome is time until an event, some subjects may be censored (event-free when observation ends), and you want to quantify how one or more covariates affect the risk of that event-far beyond the two-group comparisons a Log-Rank Test is limited to.

ScenarioEvent of InterestWhat's Being Checked
Clinical trialsDeath or disease relapseWhether treatment arm lowers the hazard of the event
Customer analyticsSubscription cancellationWhether plan type or usage predicts churn timing
Reliability engineeringComponent failureWhether manufacturing batch or load affects failure risk
Credit riskLoan defaultWhether borrower characteristics affect default hazard
Employee analyticsVoluntary attritionWhether tenure, role, or salary band predicts turnover risk

The key requirement: you have a time-to-event outcome with at least some censored observations, and you want covariate-adjusted, interpretable effect sizes-not just a survival curve comparison between two fixed groups.

Key Assumptions

  • Proportional hazards. The hazard ratio between any two subjects (or covariate levels) stays constant over the entire follow-up period-the model's namesake and most important assumption, checked in detail in Checking the Proportional Hazards Assumption.
  • Independence of censoring. Censoring must be unrelated to a subject's underlying risk of the event-a subject shouldn't be more or less likely to drop out precisely because their risk is unusually high or low (non-informative censoring).
  • Linearity of the log-hazard. Continuous covariates are assumed to affect the log-hazard linearly; a strongly non-linear true relationship (for example, U-shaped risk with age) needs transformation or splines to model correctly.
  • Independence of observations. Subjects' event times are assumed independent of one another, which can be violated by clustered data such as patients within the same hospital or repeated measures on the same subject.
  • No perfect separation or extreme multicollinearity. As with any regression on a linear predictor, highly correlated covariates or a covariate that perfectly separates events from non-events destabilizes coefficient estimates.

Hypotheses

For a single covariate \( X \) with coefficient \( \beta \), the standard significance test on a fitted Cox model is:

  • Null Hypothesis (\( H_0 \)): \( \beta = 0 \)-the covariate has no effect on the hazard (equivalently, the hazard ratio \( e^\beta = 1 \)).
  • Alternative Hypothesis (\( H_1 \)): \( \beta \neq 0 \)-the covariate is associated with a change in hazard (\( e^\beta \neq 1 \)), tested with a Wald test, score test, or likelihood ratio test on the coefficient.

(With multiple covariates, an overall likelihood ratio test can also check whether the full set of coefficients is jointly zero, analogous to an overall F-test in ordinary regression.)

The Formula, Explained

The Cox model expresses the hazard for subject \( i \) at time \( t \), given covariates \( X_i = (X_{i1}, \ldots, X_{ip}) \), as:

\[ h(t \mid X_i) = h_0(t) \cdot \exp\!\left(\beta_1 X_{i1} + \beta_2 X_{i2} + \cdots + \beta_p X_{ip}\right) \]

\( h_0(t) \) is the unspecified baseline hazard-the risk over time for a hypothetical subject with all covariates equal to zero. The exponential term is the hazard ratio multiplier: it scales that baseline risk up or down depending on the subject's covariate values, but crucially does not depend on \( t \) at all, which is exactly what makes the hazards "proportional."

For a single binary covariate (e.g., treatment = 1, control = 0), the hazard ratio comparing the two groups simplifies to:

\[ HR = \frac{h(t \mid X=1)}{h(t \mid X=0)} = e^{\beta} \]
Hazard Ratio \( e^\beta \)Interpretation
\( e^\beta = 1 \)No effect-covariate does not change risk
\( e^\beta > 1 \)Covariate increases the instantaneous risk of the event
\( e^\beta < 1 \)Covariate is protective-decreases the instantaneous risk

Partial Likelihood and Censoring

Because \( h_0(t) \) is left completely unspecified, ordinary maximum likelihood doesn't directly apply. Cox's key insight was the partial likelihood: at each observed event time \( t_j \), compare the covariates of the subject who actually had the event against the covariates of everyone still at risk (the "risk set")-still under observation and event-free just before \( t_j \). The partial likelihood is:

\[ L(\beta) = \prod_{j} \frac{\exp(\beta^\top X_j)}{\sum_{k \in R(t_j)} \exp(\beta^\top X_k)} \]

where \( R(t_j) \) is the risk set at time \( t_j \) and the product runs over every observed event. The baseline hazard \( h_0(t) \) cancels out entirely, which is exactly why it never needs to be specified. Coefficients \( \beta \) are estimated by maximizing this expression numerically.

Censored subjects still matter here-even though they never appear as the numerator in any term, they remain in every risk set \( R(t_j) \) up until the time they were censored, correctly contributing the information "this subject survived at least this long" without requiring their exact event time.

Worked Example 1: A Single Binary Covariate

Suppose 6 patients are followed in a small trial, with group = 1 for treatment and group = 0 for control. A + marks a censored observation (event-free at last follow-up):

PatientTimeEvent?Group
A4YesControl (0)
B6YesTreatment (1)
C7Censored (+)Treatment (1)
D9YesControl (0)
E10YesTreatment (1)
F12Censored (+)Control (0)

There are 4 observed event times: \( t = 4, 6, 9, 10 \). At each, we compare the subject who had the event against everyone still in the risk set:

  • t = 4 (Patient A, control): risk set = {A, B, C, D, E, F}, all 6 patients.
  • t = 6 (Patient B, treatment): risk set = {B, C, D, E, F}, 5 patients (A already had the event).
  • t = 9 (Patient D, control): risk set = {D, E, F}, 3 patients remain.
  • t = 10 (Patient E, treatment): risk set = {E, F}, 2 patients remain.

Writing \( \theta = e^\beta \) as the hazard ratio for treatment vs. control, each term in the partial likelihood contributes \( \theta \) to the numerator if the subject who had the event was in the treatment group, or \( 1 \) if in the control group, against a denominator summing \( \theta \) for each treatment subject at risk and \( 1 \) for each control subject at risk:

\[ L(\theta) = \frac{1}{3\theta + 3} \cdot \frac{\theta}{2\theta + 2} \cdot \frac{1}{\theta + 2} \cdot \frac{\theta}{\theta + 1} \]

Maximizing this numerically (standard software does this via Newton-Raphson) gives \( \hat{\theta} \approx 1.55 \), i.e., \( \hat{\beta} \approx 0.44 \). The treatment group's instantaneous risk of the event is estimated at about 1.55 times that of control-though with only 6 patients, this estimate carries a wide confidence interval and would not be statistically significant at conventional thresholds. This example is deliberately small to make the partial likelihood mechanics visible; see Python Example for how software handles this at realistic sample sizes.

Worked Example 2: Multiple Covariates

Now suppose a fitted Cox model on equipment failure data includes two covariates: age (years in service, continuous) and heavy_use (1 if operated above rated capacity, 0 otherwise), producing the following estimated coefficients:

Covariate\( \hat{\beta} \)Hazard Ratio \( e^{\hat{\beta}} \)p-value
age0.151.160.012
heavy_use0.922.510.001

Interpreting age: each additional year in service multiplies the instantaneous hazard of failure by \( e^{0.15} \approx 1.16 \)-a 16% increase in failure risk per year, holding heavy use constant, and statistically significant at the 5% level (\( p = 0.012 \)).

Interpreting heavy_use: equipment operated above rated capacity has \( e^{0.92} \approx 2.51 \) times the instantaneous hazard of failure compared to equipment operated within capacity, holding age constant-a large and highly significant effect (\( p = 0.001 \)).

For a 5-year-old machine under heavy use versus a 5-year-old machine under normal use, the combined hazard ratio is simply \( e^{0.92} \approx 2.51 \) (age cancels since both machines share the same age); for a 10-year-old heavily used machine versus a brand-new normally used machine, the combined ratio compounds multiplicatively: \( e^{0.15 \times 10} \times e^{0.92} \approx 4.48 \times 2.51 \approx 11.25 \).

Python Example

In practice, you'll fit the model with dedicated survival analysis software rather than maximizing the partial likelihood by hand. Python's lifelines.CoxPHFitter is the standard choice:

import pandas as pd
from lifelines import CoxPHFitter

# Example: time, event indicator, and covariates
data = pd.DataFrame({
    'time':       [4, 6, 7, 9, 10, 12],
    'event':      [1, 1, 0, 1, 1, 0],   # 1 = event occurred, 0 = censored
    'group':      [0, 1, 1, 0, 1, 0],   # 1 = treatment, 0 = control
})

cph = CoxPHFitter()
cph.fit(data, duration_col='time', event_col='event')

cph.print_summary()

# Check the proportional hazards assumption
cph.check_assumptions(data, p_value_threshold=0.05, show_plots=True)

Output (abbreviated):

              coef  exp(coef)  se(coef)      p
group        0.438      1.550     0.912  0.631

Concordance = 0.67
Partial AIC = 18.92
log-likelihood ratio test = 0.32 on 1 df, p=0.573

This matches Worked Example 1-a hazard ratio around 1.55 for the treatment group, with a p-value showing the effect is not statistically significant at this tiny sample size, exactly as expected. The check_assumptions call runs a Schoenfeld residual test automatically, flagging any covariate whose hazard ratio appears to change over time.

How to Interpret Results

ResultInterpretation
Hazard ratio \( \approx 1 \), p-value \( \geq 0.05 \)No significant evidence the covariate affects risk
Hazard ratio \( > 1 \), p-value \( < 0.05 \)Covariate significantly increases the hazard (higher risk)
Hazard ratio \( < 1 \), p-value \( < 0.05 \)Covariate significantly decreases the hazard (protective effect)
Wide confidence interval crossing 1Direction of effect uncertain-often a small-sample-size issue

Always report the hazard ratio with its confidence interval, not just the point estimate and p-value-a hazard ratio of 2.5 with a 95% CI of 1.8 to 3.4 tells a very different, much more convincing story than the same 2.5 with a CI of 0.6 to 11.2.

Checking the Proportional Hazards Assumption

The entire model rests on hazard ratios staying constant over time, so this assumption needs to be checked, not assumed:

  • Schoenfeld residuals test: the standard formal check-plots each covariate's residuals against time and tests for a non-zero slope; a significant trend indicates the hazard ratio for that covariate is not constant.
  • Log-log survival plots: for categorical covariates, plotting \( \log(-\log(S(t))) \) against \( \log(t) \) for each group-roughly parallel curves support the assumption; curves that cross or diverge suggest a violation.
  • Time-interaction terms: add an interaction between the suspect covariate and a function of time directly into the model; a significant interaction coefficient confirms a time-varying effect.
  • If violated: stratify by the offending covariate (allowing a separate baseline hazard per stratum), split follow-up time into intervals with different coefficients, or move to a time-varying covariate specification.
In practice.lifelines' check_assumptions() and R's cox.zph() both automate the Schoenfeld residuals test end to end-run one of these on every Cox model before trusting the reported hazard ratios.

Common Pitfalls and How to Avoid Them

  • Skipping the proportional hazards check. Reporting hazard ratios from a model that violates its central assumption can be actively misleading-always run a Schoenfeld residuals test before interpreting results.
  • Treating hazard ratio like risk ratio or odds ratio. A hazard ratio describes instantaneous risk at any moment, not cumulative probability of the event over the whole study-these three quantities are related but numerically different, especially when event rates are high.
  • Ignoring informative censoring. If subjects drop out because their risk is unusually high or low (e.g., very sick patients leaving a trial), the independence-of-censoring assumption is violated and estimates can be biased.
  • Overfitting with too many covariates relative to events. A common rule of thumb is at least 10 events per covariate; fitting a model with more covariates than the data can support produces unstable, overconfident estimates.
  • Forgetting to check for time-varying effects in covariates known to matter more early or late in follow-up (e.g., surgical risk vs. long-term recurrence risk)-consider stratification or time-interaction terms as covered in Checking the Proportional Hazards Assumption.

Advantages

  • Doesn't require specifying the shape of the baseline hazard-the semi-parametric design handles arbitrary, unknown risk patterns over time.
  • Naturally incorporates censored observations without discarding information or requiring ad-hoc imputation of missing event times.
  • Produces directly interpretable hazard ratios, making effect sizes easy to communicate to non-technical audiences.
  • Handles multiple covariates simultaneously, adjusting for confounders the way ordinary regression does.
  • Well established with mature diagnostics (Schoenfeld residuals, concordance index) for validating model fit.

Limitations

  • Depends entirely on the proportional hazards assumption. Violations, if unaddressed, invalidate the hazard ratio interpretation-see Common Pitfalls.
  • Assumes linear log-hazard relationships for continuous covariates by default; genuine non-linear effects require explicit transformation or spline terms.
  • Sensitive to the number of events, not just sample size. A large dataset with few actual events still yields unstable, low-power estimates.
  • Assumes non-informative censoring. Biased estimates result if the reason a subject is censored is correlated with their underlying risk.
  • Baseline hazard is left unestimated by default, so absolute risk or survival probability predictions require an additional step (e.g., the Breslow estimator) beyond the hazard ratios themselves.

When NOT to Use It

  • When the proportional hazards assumption is clearly and persistently violated for a key covariate and cannot be resolved by stratification or time-interaction terms-consider an accelerated failure time model instead.
  • When you only need to compare survival between two or three fixed groups with no covariate adjustment-a simple Log-Rank Test or Kaplan-Meier comparison is more appropriate and easier to communicate.
  • When the number of observed events is very small relative to the number of covariates you want to include, risking unstable or non-converging estimates.
  • When censoring is clearly informative (related to the outcome itself) and cannot be reasonably assumed independent.
  • When your primary interest is absolute, individual-level probability of survival at a specific time rather than relative risk-parametric survival models (Weibull, log-normal) may be more directly suited.

Cox Model vs Kaplan-Meier vs Log-Rank vs Logistic Regression

AspectCox Proportional HazardsKaplan-MeierLog-Rank TestLogistic Regression
What it modelsHazard as a function of covariatesNon-parametric survival curve estimateWhether survival curves differ between groupsProbability of a binary outcome (no time dimension)
Handles censoringYes, natively via partial likelihoodYes, nativelyYes, nativelyNo-censored subjects must be dropped or recoded, losing information
CovariatesAny number, continuous or categoricalNone-descriptive onlyNone beyond the grouping variableAny number, but ignores timing entirely
OutputHazard ratios with confidence intervalsSurvival probability curve over timeSingle p-value for curve differenceOdds ratios (no time-to-event information)
Typical useCovariate-adjusted risk modelingVisualizing survival experience of a cohortSimple group comparison of survivalFixed-time outcome, no censoring or timing needed

Common Misconceptions

  • "A hazard ratio of 2 means the event happens twice as often overall." Not quite-it means the instantaneous risk at any moment is doubled, holding the proportional hazards assumption. Cumulative probability differences over the full study period depend on the baseline hazard shape too, as discussed in Common Pitfalls.
  • "Censored subjects are wasted data and should be dropped." The opposite is true-the entire reason the Cox model exists is to use censored subjects' partial information correctly, as shown in Partial Likelihood and Censoring.
  • "The Cox model requires knowing the shape of the baseline hazard." No-that is precisely what makes it semi-parametric; \( h_0(t) \) is left unspecified and cancels out of the partial likelihood entirely.
  • "A non-significant hazard ratio means the covariate has no effect." It means there is insufficient evidence of an effect at the observed sample size-see Worked Example 1, where a hazard ratio of 1.55 was not statistically significant purely due to a very small sample.
  • "The proportional hazards assumption only matters for the exposure of interest." Every covariate in the model should be checked-a violation in a confounding variable can distort estimates for the covariate you actually care about too.

Interview Questions

  1. Explain the proportional hazards assumption in your own words, and describe how you would check it in practice.
  2. What is partial likelihood, and why does it let the Cox model avoid specifying a baseline hazard function?
  3. How does the Cox model use censored observations, and why is this an improvement over discarding them?
  4. Derive the interpretation of a hazard ratio of \( e^\beta = 1.5 \) for a one-unit increase in a continuous covariate.
  5. What would you do if the Schoenfeld residuals test indicates a covariate violates the proportional hazards assumption?
  6. Compare and contrast the Cox Proportional Hazards Model with logistic regression for modeling a binary outcome that also has a time-to-event component.
  7. Why is "at least 10 events per covariate" a commonly cited rule of thumb, and what happens if it's violated?
  8. What is the difference between a hazard ratio and a risk ratio (relative risk), and when do they diverge most?
  9. How would you extend the Cox model to handle a covariate whose value changes during follow-up?
  10. What does "informative censoring" mean, and why does it threaten the validity of Cox model estimates?

Frequently Asked Questions

  • The Cox Proportional Hazards Test-more precisely, the significance tests attached to a fitted Cox Proportional Hazards Model-checks whether one or more covariates meaningfully change the instantaneous risk of an event happening, such as death, disease recurrence, equipment failure, or customer churn, while correctly handling subjects whose event time is only partially known because they were censored during the observation window.
  • The model specifies the hazard function as h(t|X) = h0(t) * exp(b1*X1 + b2*X2 + ... + bp*Xp), where h0(t) is an unspecified, non-parametric baseline hazard shared by everyone, X1 through Xp are the covariates, and b1 through bp are coefficients estimated by maximizing a partial likelihood. Exponentiating any coefficient, exp(b_i), gives that covariate's hazard ratio, holding the other covariates fixed.
  • A hazard ratio (HR) of exactly 1 means the covariate has no effect on the instantaneous risk of the event. An HR above 1 means the covariate increases risk-an HR of 1.5 means the event occurs at 1.5 times the rate at any given instant, compared to a one-unit-lower value of that covariate, holding everything else constant. An HR below 1 means the covariate is protective, lowering the instantaneous risk of the event.
  • The proportional hazards assumption is the requirement that the hazard ratio between any two subjects, or between any two levels of a covariate, remains constant across the entire follow-up period-even though the underlying baseline hazard itself is free to rise and fall over time. It is the model's central assumption and is typically checked using a statistical test on Schoenfeld residuals: if the residuals for a covariate trend systematically with time, that covariate violates the assumption.
  • Censoring means the exact event time for a subject is not fully observed. The most common form, right-censoring, happens when a subject is still event-free when the study ends, drops out, or is lost to follow-up-so all that is known is that their true event time is at least as long as their last observed time. The Cox model's partial likelihood is specifically constructed to use this partial information correctly rather than discarding censored subjects.
  • The Log-Rank Test compares entire survival curves between a small number of discrete groups (for example, treatment versus control) and cannot incorporate continuous covariates or adjust for confounding variables. The Cox Proportional Hazards Test generalizes this: it can include any number of continuous and categorical covariates simultaneously, produces an interpretable effect size for each one through its hazard ratio, and adjusts for multiple predictors at once-which is why it is the standard tool once more than a simple two-group comparison is needed.
  • Yes. The standard Cox model assumes covariates are fixed at baseline, but an extended version-the time-varying (or time-dependent) Cox model-allows covariate values to change during follow-up, such as a lab measurement that is re-taken at multiple visits. This requires restructuring the dataset into multiple time intervals per subject, which most survival analysis software, including lifelines and R's survival package, supports directly.

Key Takeaways

  • The Cox Proportional Hazards Model relates covariates to the hazard function via \( h(t|X) = h_0(t) \cdot \exp(\beta^\top X) \), leaving the baseline hazard \( h_0(t) \) completely unspecified.
  • Coefficients are estimated by maximizing a partial likelihood that compares the subject who had each event against everyone still at risk-correctly using censored observations without discarding them.
  • Exponentiating a coefficient gives a hazard ratio: above 1 means increased risk, below 1 means a protective effect, and 1 means no effect.
  • The model's core assumption-proportional hazards-means the hazard ratio must stay constant over time, and should always be checked with Schoenfeld residuals before trusting results.
  • In Python, lifelines.CoxPHFitter fits the model, reports hazard ratios and p-values, and check_assumptions() automates the proportional hazards diagnostic.
  • Unlike the Log-Rank Test, the Cox model handles multiple covariates simultaneously and quantifies effect size directly, making it the standard tool once more than a simple two-group survival comparison is needed.
  • If the proportional hazards assumption is violated, stratify by the offending covariate, add time-interaction terms, or move to a time-varying covariate specification, as outlined in Checking the Proportional Hazards Assumption.

The Cox Proportional Hazards Model earns its place as the default tool in survival analysis because it threads a difficult needle: it lets you quantify exactly how much a covariate changes the risk of an event, adjust for multiple confounders at once, and correctly use every subject's data-including those who were censored-without ever having to guess the shape of risk over time. That flexibility comes with one non-negotiable condition: the hazard ratio has to actually stay proportional across the whole follow-up period, which is why checking that assumption isn't optional.

The two worked examples above show the method end to end-from building up the partial likelihood term by term on a handful of patients, to reading a fitted model's hazard ratios and combining them across multiple covariates on realistic equipment-failure data. Fit the model, run check_assumptions() or its equivalent, report hazard ratios alongside their confidence intervals, and the Cox Proportional Hazards Test becomes one of the most informative and defensible tools available for any time-to-event question.