[R]R言語で生存時間分析

生存時間分析

ある時点から興味のあるイベントが起きるまでの時間とイベントとの間の関係に関する分析。
以下のような解析を行う

  • 生存率の推定(Kaplan-Meier曲線)
  • 2郡の生存率の比較 (Log-Rank検定)
  • 生存率と共変量との関係の解明 (Cox回帰)

また、イベントの例としては、以下のようなものがある。

  • 機械システムや製品の故障
  • 疾患の病気の再発や死亡

データの準備

ここでは、survivalパッケージにあるデータセットcolonを用いる。

  • colon : Stage B/Cの結腸癌患者を対象とした術後補助化学療法の比較臨床試験データ
> library(survival)
 要求されたパッケージ splines をロード中です 
> colon.OS <- subset(colon, colon$etype==2) #死亡に関するデータのみを取り出す

Kaplan-Meier法による生存時間分布の推定

survfit関数を使って、生存時間分布を推定することが出来る

  • 生存時間分布の推定
> result.KM <- survfit(Surv(time, status)~rx, data=colon.OS)
> result.KM
Call: survfit(formula = Surv(time, status) ~ rx, data = colon.OS)

           records n.max n.start events median 0.95LCL 0.95UCL
rx=Obs         315   315     315    168   2083    1656    2789
rx=Lev         310   310     310    161   2152    1540      NA
rx=Lev+5FU     304   304     304    123     NA    2725      NA
  • Kaplan-Meier曲線
> plot(result.KM, lty=1:3, xlim=c(0, 3500), ylim=c(0,1), xlab="Time", ylab="Event Free Fate", main="Survival Curve")
> abline(0.5, 0)
> plot(result.KM, lty=1:3, xlim=c(0, 3500), ylim=c(0,1), xlab="Time", ylab="Event Free Fate", main="Survival Curve")
> abline(0.5, 0)


  • Log-Logプロット
> plot(result.KM, lty=1:3, fun="cloglog", xlab="Time", ylab="log(-log(Event Free Rate))", main="Log-log Curve")
> legend(20, 0, legend=c("Obs", "Levamisole", "Levamisole+5-FU"), lty=1:3, bty="n")


Log-Rank検定

2郡以上の観測値が得られた場合、郡ごとに生存曲線の間の有意性について検定する必要がある。
最も広く用いられている検定法は、Log-Rank検定法で、survdiff関数で実行する事が出来る。

> result.LR <- survdiff(Surv(time, status)~rx, 
+ subset=(rx %in% c("Obs", "Lev+5FU")), data=colon.OS)
> result.LR
Call:
survdiff(formula = Surv(time, status) ~ rx, data = colon.OS, 
    subset = (rx %in% c("Obs", "Lev+5FU")))

             N Observed Expected (O-E)^2/E (O-E)^2/V
rx=Obs     315      168      141      5.12      9.97
rx=Lev+5FU 304      123      150      4.82      9.97

 Chisq= 10  on 1 degrees of freedom, p= 0.00159 

Cox比例ハザードモデルによるハザード比の推定

Cox比例ハザードモデルは、イベントに影響を及ぼす複数の因子(共変量)の影響を解析する代表的なモデル。
Cox比例ハザードモデルのパラメータ推定するには、coxph関数を用いる。method引数で、推定法を指定する事が出来、ここでは、ブレスローの近似法を指定している。

> result.Cox <- coxph(Surv(time, status)~rx+node4+age+obstruct+perfor+adhere+nodes+differ+extent+surg+node4, method="breslow", data=na.omit(colon.OS))
> summary(result.Cox)
Call:
coxph(formula = Surv(time, status) ~ rx + node4 + age + obstruct + 
    perfor + adhere + nodes + differ + extent + surg + node4, 
    data = na.omit(colon.OS), method = "breslow")

  n= 888, number of events= 430 

               coef exp(coef)  se(coef)      z Pr(>|z|)    
rxLev     -0.041393  0.959452  0.114366 -0.362 0.717404    
rxLev+5FU -0.362772  0.695745  0.122066 -2.972 0.002959 ** 
node4      0.676559  1.967096  0.142361  4.752 2.01e-06 ***
age        0.007537  1.007565  0.004181  1.803 0.071442 .  
obstruct   0.268871  1.308486  0.120310  2.235 0.025430 *  
perfor     0.017162  1.017310  0.269935  0.064 0.949307    
adhere     0.170110  1.185435  0.131738  1.291 0.196611    
nodes      0.043738  1.044709  0.015239  2.870 0.004102 ** 
differ     0.137941  1.147908  0.100818  1.368 0.171244    
extent     0.446006  1.562061  0.118344  3.769 0.000164 ***
surg       0.240548  1.271946  0.106118  2.267 0.023402 *  
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1 

          exp(coef) exp(-coef) lower .95 upper .95
rxLev        0.9595     1.0423    0.7668    1.2005
rxLev+5FU    0.6957     1.4373    0.5477    0.8838
node4        1.9671     0.5084    1.4882    2.6002
age          1.0076     0.9925    0.9993    1.0159
obstruct     1.3085     0.7642    1.0336    1.6564
perfor       1.0173     0.9830    0.5994    1.7267
adhere       1.1854     0.8436    0.9157    1.5347
nodes        1.0447     0.9572    1.0140    1.0764
differ       1.1479     0.8712    0.9421    1.3987
extent       1.5621     0.6402    1.2387    1.9698
surg         1.2719     0.7862    1.0331    1.5660

Rsquare= 0.145   (max possible= 0.998 )
Likelihood ratio test= 139.5  on 11 df,   p=0
Wald test            = 148.3  on 11 df,   p=0
Score (logrank) test = 158.8  on 11 df,   p=0
比例ハザード性の仮定が成り立っているかを確認

Cox比例ハザードモデルは、ハザード比が時間によらず一定であることを前提としているため、この仮定を吟味する必要がある。
これは、cox.zph関数を実行することで出来る。

> result.coxzph <- cox.zph(result.Cox)
> result.coxzph
              rho   chisq        p
rxLev     -0.0930  3.8661 4.93e-02
rxLev+5FU -0.0711  2.2282 1.36e-01
node4     -0.1327  7.0797 7.80e-03
age       -0.0626  1.8782 1.71e-01
obstruct  -0.1496 10.1433 1.45e-03
perfor     0.0534  1.3010 2.54e-01
adhere     0.0326  0.4741 4.91e-01
nodes      0.1013  3.5367 6.00e-02
differ    -0.1588 12.7542 3.55e-04
extent    -0.0778  2.5097 1.13e-01
surg      -0.0118  0.0597 8.07e-01
GLOBAL         NA 37.5164 9.44e-05

また、plot関数で、比例性の診断プロットを出力することが出来る。
スプライン平滑か曲線の傾向に、時間に伴う明らかな変化パターンが見られなければ、比例ハザードの仮定には問題がないと言われている。
個別の変数に比例ハザードの仮定が充たされていない場合は、変数の交差項をモデルに導入するような試みが必要になる。

> op <- par(mfrow=c(2,2), mar=c(4.5, 4, 1, 1))
> plot(result.coxzph, df=2); par(op)



変数選択

回帰分析と同様に、Cox比例ハザードモデルでもsetAIC関数でモデルを構築出来る。

> library(MASS)
> result.step <- stepAIC(result.Cox)

...(省略)...


> summary(result.step)
Call:
coxph(formula = Surv(time, status) ~ rx + node4 + age + obstruct + 
    nodes + differ + extent + surg, data = na.omit(colon.OS), 
    method = "breslow")

  n= 888, number of events= 430 

               coef exp(coef)  se(coef)      z Pr(>|z|)    
rxLev     -0.038729  0.962011  0.114243 -0.339  0.73461    
rxLev+5FU -0.364097  0.694824  0.121994 -2.985  0.00284 ** 
node4      0.674685  1.963414  0.141758  4.759 1.94e-06 ***
age        0.008063  1.008096  0.004159  1.939  0.05253 .  
obstruct   0.270757  1.310957  0.119359  2.268  0.02330 *  
nodes      0.043733  1.044703  0.015168  2.883  0.00394 ** 
differ     0.152120  1.164300  0.100346  1.516  0.12953    
extent     0.461643  1.586679  0.118520  3.895 9.82e-05 ***
surg       0.241874  1.273633  0.106109  2.279  0.02264 *  
---
Signif. codes:  0***0.001**0.01*0.05 ‘.’ 0.1 ‘ ’ 1 

          exp(coef) exp(-coef) lower .95 upper .95
rxLev        0.9620     1.0395    0.7690    1.2034
rxLev+5FU    0.6948     1.4392    0.5471    0.8825
node4        1.9634     0.5093    1.4871    2.5922
age          1.0081     0.9920    0.9999    1.0163
obstruct     1.3110     0.7628    1.0375    1.6565
nodes        1.0447     0.9572    1.0141    1.0762
differ       1.1643     0.8589    0.9564    1.4174
extent       1.5867     0.6302    1.2578    2.0016
surg         1.2736     0.7852    1.0345    1.5681

Rsquare= 0.144   (max possible= 0.998 )
Likelihood ratio test= 137.9  on 9 df,   p=0
Wald test            = 146.7  on 9 df,   p=0
Score (logrank) test = 156.7  on 9 df,   p=0
生存時間の推定

構築したモデルによる生存時間の当てはめは、survfit関数を用いて行うことが出来る。
また、plot関数で生存曲線および信頼区間を出力することが出来る。

> result.step.fit <- survfit(result.step)
> plot(result.step.fit)