Survival Analysis in Medical Research

Code by Mark Clements

Example 8.3: Chemotherapy in ovarian cancer patients

library(knitr) # kable
library(collett) # leukaemia
library(survival) # coxph

Attaching package: 'survival'
The following objects are masked from 'package:collett':

    bladder, kidney, lung, myeloma, ovarian
kable(collett::ovarian, "html")
patient time status treat age rdisease perf
1 156 1 1 66 2 2
2 1040 0 1 38 2 2
3 59 1 1 72 2 1
4 421 0 2 53 2 1
5 329 1 1 43 2 1
6 769 0 2 59 2 2
7 365 1 2 64 2 1
8 770 0 2 57 2 1
9 1227 0 2 59 1 2
10 268 1 1 74 2 2
11 475 1 2 59 2 2
12 1129 0 2 53 1 1
13 464 1 2 56 2 2
14 1206 0 2 44 2 1
15 638 1 1 56 1 2
16 563 1 2 55 1 2
17 1106 0 1 44 1 1
18 431 1 1 50 2 1
19 855 0 1 43 1 2
20 803 0 1 39 1 1
21 115 1 1 74 2 1
22 744 0 2 50 1 1
23 477 0 1 64 2 1
24 448 0 1 56 1 2
25 353 1 2 63 1 2
26 377 0 2 58 1 1
str(collett::ovarian)
'data.frame':   26 obs. of  7 variables:
 $ patient : int  1 2 3 4 5 6 7 8 9 10 ...
 $ time    : int  156 1040 59 421 329 769 365 770 1227 268 ...
 $ status  : int  1 0 1 0 1 0 1 0 0 1 ...
 $ treat   : int  1 1 1 2 1 2 2 2 2 1 ...
 $ age     : int  66 38 72 53 43 59 64 57 59 74 ...
 $ rdisease: int  2 2 2 2 2 2 2 2 1 2 ...
 $ perf    : int  2 2 1 1 1 2 1 1 2 2 ...
fit1 = coxph(Surv(time,status)~age+treat,collett::ovarian)
summary(fit1)
Call:
coxph(formula = Surv(time, status) ~ age + treat, data = collett::ovarian)

  n= 26, number of events= 12 

          coef exp(coef) se(coef)      z Pr(>|z|)   
age    0.14657   1.15786  0.04585  3.196  0.00139 **
treat -0.79593   0.45116  0.63294 -1.258  0.20857   
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

      exp(coef) exp(-coef) lower .95 upper .95
age      1.1579     0.8637    1.0583     1.267
treat    0.4512     2.2165    0.1305     1.560

Concordance= 0.794  (se = 0.079 )
Likelihood ratio test= 15.82  on 2 df,   p=4e-04
Wald test            = 13.55  on 2 df,   p=0.001
Score (logrank) test = 18.61  on 2 df,   p=9e-05
as.numeric(-2*logLik(fit1))
[1] 54.14753
fit2 = coxph(Surv(time,status)~age+treat+tt(age),collett::ovarian,
             tt=function(x,t,...) x*t)
summary(fit2)
Call:
coxph(formula = Surv(time, status) ~ age + treat + tt(age), data = collett::ovarian, 
    tt = function(x, t, ...) x * t)

  n= 26, number of events= 12 

              coef  exp(coef)   se(coef)      z Pr(>|z|)  
age      0.2156499  1.2406679  0.1126093  1.915   0.0555 .
treat   -0.6635945  0.5149968  0.6695492 -0.991   0.3216  
tt(age) -0.0002031  0.9997969  0.0002832 -0.717   0.4733  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

        exp(coef) exp(-coef) lower .95 upper .95
age        1.2407      0.806    0.9950     1.547
treat      0.5150      1.942    0.1386     1.913
tt(age)    0.9998      1.000    0.9992     1.000

Concordance= 0.794  (se = 0.083 )
Likelihood ratio test= 16.36  on 3 df,   p=0.001
Wald test            = 12.44  on 3 df,   p=0.006
Score (logrank) test = 18.92  on 3 df,   p=3e-04
as.numeric(-2*logLik(fit2))
[1] 53.61321
event_times = unique(subset(collett::ovarian,status==1)$time)
ovar = survSplit(Surv(time,status)~., data=collett::ovarian,
                 cut=event_times) |>
    transform(t=time) 
fit3 = coxph(Surv(tstart,time,status)~age+treat+age:t,data=ovar)
summary(fit3)
Call:
coxph(formula = Surv(tstart, time, status) ~ age + treat + age:t, 
    data = ovar)

  n= 244, number of events= 12 

            coef  exp(coef)   se(coef)      z Pr(>|z|)  
age    0.2156499  1.2406679  0.1126093  1.915   0.0555 .
treat -0.6635945  0.5149968  0.6695492 -0.991   0.3216  
age:t -0.0002031  0.9997969  0.0002832 -0.717   0.4733  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

      exp(coef) exp(-coef) lower .95 upper .95
age      1.2407      0.806    0.9950     1.547
treat    0.5150      1.942    0.1386     1.913
age:t    0.9998      1.000    0.9992     1.000

Concordance= 0.794  (se = 0.083 )
Likelihood ratio test= 16.36  on 3 df,   p=0.001
Wald test            = 12.44  on 3 df,   p=0.006
Score (logrank) test = 18.92  on 3 df,   p=3e-04
as.numeric(-2*logLik(fit3))
[1] 53.61321
anova(fit3)
Analysis of Deviance Table
 Cox model: response is Surv(tstart, time, status)
Terms added sequentially (first to last)

       loglik   Chisq Df Pr(>|Chi|)    
NULL  -34.985                          
age   -27.852 14.2667  1  0.0001586 ***
treat -27.074  1.5557  1  0.2122988    
age:t -26.807  0.5343  1  0.4647963    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1