So far, have seen:
response variable counted or measured (regression)
response variable categorized (logistic regression)
But what if response is time until event (eg. time of survival after surgery)?
Additional complication: event might not have happened at end of study (eg. patient still alive). But knowing that patient has “not died yet” presumably informative. Such data called censored.
Enter survival analysis, in particular the “Cox proportional hazards model”.
Explanatory variables in this context often called covariates.
survival if not done. Also use broom and marginaleffects from earlier.time are the intervals (in years) between first treatment and either death or the end of the study (January 1, 1983).status records whether the patient was dead or alive at the end of the study.stage is one of A through D, with A being least serious and D being most serious.stage and age.time and status: [1] 0.6 1.3 2.4 2.5+ 3.2 3.2+ 3.3 3.3+ 3.5
[10] 3.5 4.0 4.0 4.3 4.5+ 4.5+ 5.3 5.5+ 5.9+
[19] 5.9+ 6.0 6.1+ 6.2+ 6.4 6.5 6.5+ 6.7+ 7.0+
[28] 7.4 7.4+ 8.1+ 8.1+ 9.6+ 10.7+ 0.2 1.8 2.0
[37] 2.2+ 2.6+ 3.3+ 3.6 3.6+ 4.0 4.3+ 4.3+ 5.0+
[46] 6.2 7.0 7.5+ 7.6+ 9.3+ 0.3 0.3 0.5 0.7
[55] 0.8 1.0 1.3 1.6 1.8 1.9 1.9 3.2 3.5
[64] 3.7+ 4.5+ 4.8+ 4.8+ 5.0 5.0+ 5.1+ 6.3 6.4
[73] 6.5+ 7.8 8.0+ 9.3+ 10.1+ 0.1 0.3 0.4 0.8
[82] 0.8 1.0 1.5 2.0 2.3 2.9+ 3.6 3.8 4.3+
Patients with a + by survival time were still alive at end.
stage is categorical with 4 levels, so to see what we can remove, use drop1:Age is not significant (has nothing to add to prediction over and above stage)
There is definitely a significant effect of stage.
Remove age and re-fit:
stage effectCall:
coxph(formula = Surv(time, status == "dead") ~ stage, data = larynx)
n= 90, number of events= 50
coef exp(coef) se(coef) z Pr(>|z|)
stageB 0.06481 1.06696 0.45843 0.141 0.8876
stageC 0.61481 1.84930 0.35519 1.731 0.0835 .
stageD 1.73490 5.66838 0.41939 4.137 3.52e-05 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
exp(coef) exp(-coef) lower .95 upper .95
stageB 1.067 0.9372 0.4344 2.62
stageC 1.849 0.5407 0.9219 3.71
stageD 5.668 0.1764 2.4916 12.90
Concordance= 0.668 (se = 0.037 )
Likelihood ratio test= 16.49 on 3 df, p=9e-04
Wald test = 19.24 on 3 df, p=2e-04
Score (logrank) test = 22.88 on 3 df, p=4e-05
coef column like regression slopesAll depends on hazard rate, which is based on probability that event happens in the next short time period, given that event has not happened yet:
\(X\) denotes time to event, \(\delta\) is small time interval:
\(h(t) = P(X \le t + \delta | X \ge t) / \delta\)
if \(h(t)\) large, event likely to happen soon (lifetime short)
if \(h(t)\) small, event unlikely to happen soon (lifetime long).
want to model hazard rate
but hazard rate always positive, so actually model log of hazard rate
modelling how (log-)hazard rate depends on other things eg \(X_1 =\) age, \(X_2 =\) treatment, with the \(\beta\) being regression coefficients:
Cox model \(h(t)=h_0(t)\exp(\beta_0+\beta_1X_1+\beta_2 X_2+\cdots)\), or:
\(\log(h(t)) = \log(h_0(t)) + \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \cdots\)
like a generalized linear model with log link.
plot_predictions from marginaleffects.condition, inputs are (in order):
condition:summary output.stagenew with explanatory variable values and times to predict forkidney dataset from the KMsurv package (install first):delta: 1 = infected, 0 not (censored, usually from catheter failure)type: 1 = surgical, 2 = percutaneouscox.zph. Gives a P-value, and also a graph to help understand why proportional hazards fails (if it does).Proportional hazards is rejected (P-value 0.0033).
type in the model, here 0.6:surgical vs percutaneous)surgical vs percutaneous)stage has 4 levels, so get test and graph for each one vs baseline A: chisq df p
stageB 0.18227 1 0.669
stageC 3.26317 1 0.071
stageD 0.00393 1 0.950
GLOBAL 3.58948 3 0.309
survival package has lung: data set measuring survival in patients with advanced lung cancer.
Along with survival time, number of “performance scores” included, measuring how well patients can perform daily activities.
Sometimes high good, but sometimes bad!
Variables below, from the data set help file (?lung).
inst time status age
Min. : 1.00 Min. : 5.0 Min. :1.000 Min. :39.00
1st Qu.: 3.00 1st Qu.: 166.8 1st Qu.:1.000 1st Qu.:56.00
Median :11.00 Median : 255.5 Median :2.000 Median :63.00
Mean :11.09 Mean : 305.2 Mean :1.724 Mean :62.45
3rd Qu.:16.00 3rd Qu.: 396.5 3rd Qu.:2.000 3rd Qu.:69.00
Max. :33.00 Max. :1022.0 Max. :2.000 Max. :82.00
NAs :1
sex ph.ecog ph.karno pat.karno
Min. :1.000 Min. :0.0000 Min. : 50.00 Min. : 30.00
1st Qu.:1.000 1st Qu.:0.0000 1st Qu.: 75.00 1st Qu.: 70.00
Median :1.000 Median :1.0000 Median : 80.00 Median : 80.00
Mean :1.395 Mean :0.9515 Mean : 81.94 Mean : 79.96
3rd Qu.:2.000 3rd Qu.:1.0000 3rd Qu.: 90.00 3rd Qu.: 90.00
Max. :2.000 Max. :3.0000 Max. :100.00 Max. :100.00
NAs :1 NAs :1 NAs :3
meal.cal wt.loss
Min. : 96.0 Min. :-24.000
1st Qu.: 635.0 1st Qu.: 0.000
Median : 975.0 Median : 7.000
Mean : 928.8 Mean : 9.832
3rd Qu.:1150.0 3rd Qu.: 15.750
Max. :2600.0 Max. : 68.000
NAs :47 NAs :14
inst time status age
Min. : 1.00 Min. : 5.0 Min. :1.000 Min. :39.00
1st Qu.: 3.00 1st Qu.: 174.5 1st Qu.:1.000 1st Qu.:57.00
Median :11.00 Median : 268.0 Median :2.000 Median :64.00
Mean :10.71 Mean : 309.9 Mean :1.719 Mean :62.57
3rd Qu.:15.00 3rd Qu.: 419.5 3rd Qu.:2.000 3rd Qu.:70.00
Max. :32.00 Max. :1022.0 Max. :2.000 Max. :82.00
sex ph.ecog ph.karno pat.karno
Min. :1.000 Min. :0.0000 Min. : 50.00 Min. : 30.00
1st Qu.:1.000 1st Qu.:0.0000 1st Qu.: 70.00 1st Qu.: 70.00
Median :1.000 Median :1.0000 Median : 80.00 Median : 80.00
Mean :1.383 Mean :0.9581 Mean : 82.04 Mean : 79.58
3rd Qu.:2.000 3rd Qu.:1.0000 3rd Qu.: 90.00 3rd Qu.: 90.00
Max. :2.000 Max. :3.0000 Max. :100.00 Max. :100.00
meal.cal wt.loss
Min. : 96.0 Min. :-24.000
1st Qu.: 619.0 1st Qu.: 0.000
Median : 975.0 Median : 7.000
Mean : 929.1 Mean : 9.719
3rd Qu.:1162.5 3rd Qu.: 15.000
Max. :2600.0 Max. : 68.000
No missing values left.
All these variables are recorded as numbers, though status, sex are actually categorical:
inst [1] "inst" "time" "status" "age" "sex"
[6] "ph.ecog" "ph.karno" "pat.karno" "meal.cal" "wt.loss"
status being dead:“Dot” means “all the other variables”; list ones to explicitly exclude.
Some of these are definitely not significant:
sex and ph.ecog definitely significant here
age, pat.karno and meal.cal definitely not
step(Output is long, suppressed)
Try taking out those marginally significant ones:
and test whether that was sensible:
Only just.
Call:
coxph(formula = Surv(time, status == "dead") ~ sex + ph.ecog,
data = lung.complete)
n= 167, number of events= 120
coef exp(coef) se(coef) z Pr(>|z|)
sexmale 0.5101 1.6655 0.1969 2.591 0.009579 **
ph.ecog 0.4825 1.6201 0.1323 3.647 0.000266 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
exp(coef) exp(-coef) lower .95 upper .95
sexmale 1.665 0.6004 1.132 2.45
ph.ecog 1.620 0.6172 1.250 2.10
Concordance= 0.641 (se = 0.031 )
Likelihood ratio test= 19.48 on 2 df, p=6e-05
Wald test = 19.35 on 2 df, p=6e-05
Score (logrank) test = 19.62 on 2 df, p=5e-05
Both remaining variables strongly significant.
Nature of effect on survival time? Consider later.
Picture?
sex and ph.ecog score using plot_predictionstime) to the condition.sex:sex = 2) have better survival than males.ph.ecog score, but the male-female comparison is the same for any score.ph.ecog score:ph.ecog score is better.ph.ecog graph was for males.ph.ecog scoresex of 1).ph.ecog score (above and below on each facet), and the effect of males (left) vs. females (right).ph.ecog scale (compare the red curve on the left facet with the green curve on the right facet).Can we put the male and female survival curves on the same plot?
Try building plot ourselves:
Call:
coxph(formula = Surv(time, status == "dead") ~ sex + ph.ecog,
data = lung.complete)
n= 167, number of events= 120
coef exp(coef) se(coef) z Pr(>|z|)
sexmale 0.5101 1.6655 0.1969 2.591 0.009579 **
ph.ecog 0.4825 1.6201 0.1323 3.647 0.000266 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
exp(coef) exp(-coef) lower .95 upper .95
sexmale 1.665 0.6004 1.132 2.45
ph.ecog 1.620 0.6172 1.250 2.10
Concordance= 0.641 (se = 0.031 )
Likelihood ratio test= 19.48 on 2 df, p=6e-05
Wald test = 19.35 on 2 df, p=6e-05
Score (logrank) test = 19.62 on 2 df, p=5e-05
ph.ecog score) equal.ph.ecog score goes with a higher hazard of death (positive coef). So patients with a lower score are more likely to survive longer, all else (sex) equal.ph.ecog) and categorical with two levels (sex): chisq df p
sex 1.24 1 0.266
ph.ecog 5.27 1 0.022
GLOBAL 6.19 2 0.045
ph.ecog does not show proportional hazards.
sex graph (left) goes more or less straight across (good).ph.ecog graph (right) seems to dip after about 300 days, so hazard of a higher ph.ecog score is higher earlier (not constant over time).ph.ecog score as having a varying effect over time (for example, it only has an effect up to 300 days).
Comments
stage(categorical)?