在進行存活分析時,可以透過 Log-rank test 來比較組別之間的存活曲線是否有顯著差異。但當自變項是連續變項
或自變項超過2個以上
時的分析時,就需要透過 Cox Regression (Cox Proportional Hazard Model)
來達成。Cox Regression Model 是使用有母數分析的預測方式,用以分析影響死亡率的變數(或影響存活率的重要因子)。在討論 cox regression 時有二個部分需要先釐清,即 存活函式 與 風險函式:
目的是呈現在某特定時間點下,個案可以活過此特定時間點的機率為何。
\[ S(t) = P(T > t) = \int_t^{\infty}f(u)du \]
其中 \(t\) 為時間點,\(S(0)=1\), \(S(\infty)=0\)。
\[ h(t) = \frac{\frac{-d[S(t)]}{dt}}{S(t)} = \frac{f(t)}{S(t)} \\ S(t) = exp(-\int_0^th(u)du) \]
其中 \(t\) 為時間點,風險函式 \(h(t)\) 值與存活時間有關,此代表在某一時間點下,事件機率(死亡)除以生存函式的值。若時間越久 (\(t\) 越大),存活函式 \(S(t)\) 越小 (存活函式為遞減函式),假設死亡機率密度 \(f(t)\) 對任何時間點都一樣,則風險函式 \(h(t)\) 值越大,預期存活時間短。
在經典的 Cox Regression 的等比例風險假設(Proportional hazard assumption, PH assumption)假設下,針對某一危險因子而言,其風險比,不能隨著時間而有所改變,必須要固定。。
由上可之,推導 Cox Regression 可得:
\[ h(t) = \lambda \\ S(t) = exp(-\int_0^th(u)du) = exp(-\lambda t) = e^{-\lambda t} \\ f(t) = h(t) * S(t) = \lambda * e^{-\lambda t} \]
而因 \(\lambda\) 為一定值,故可以推出 Cox Regression 為:
\[ log(HR(x))=log(\frac{h(t|x)}{h_0(t)}) = \beta_1{x_1} + \beta_2{x_2} + ... + \beta_k{x_k} + \varepsilon \]
此即為迴歸方程式。Hazard Ratio (\(HR\)) 表示某個時間下會發生事件的風險比,而 \(HR(x)\) 表示在給定 x 下會發生事件的風險比,x 即是自變項的數值,如年齡90歲便是一個數值 x。\(h(t|x)\) 表示在第 \(t\) 個時間點時,給定 x 值時的風險。\(h_0(t)\) 表示在第 \(t\) 個時間點時的基礎風險。而 Hazard Ratio (\(HR\)) 計算範例為當僅有一變項 \(x_1\),\(x_1=1\) 表示為男性,\(x_1=0\) 表示為女性,則 \(exp(\beta_1)\) 為男性相對於女性的危險比率,且 \(HR=\frac{exp(\beta_0 + \beta_1)}{exp(\beta_0)}\)。
Cox Regression 不僅可以用來分析病因與死亡率之間的關係,更可以延伸至企業倒閉風險分析等議題上。
於 R 實作中,可以透過套件 survival 來實現存活分析。
packageName <- c("survival")
for(i in 1:length(packageName)) {
if(!(packageName[i] %in% rownames(installed.packages()))) {
install.packages(packageName[i])
}
}
lapply(packageName, require, character.only = TRUE)
## Loading required package: survival
## [[1]]
## [1] TRUE
函式名稱 | 函式用途 |
---|---|
Surv | 創造一個存活分析的物件,通常在迴歸公式中代表應變數(response variable) |
coxph | Fit Proportional Hazards Regression Model |
coxph.control | 控制 coxph 擬合的輔助參數 |
cox.zph | 測試迴歸模型中的比例風險假設 |
cox.detail | Cox 迴歸模型的細節,此函式會回傳在每個獨立時間下的 1 階, 2 階的導數矩陣 |
strata | 用來分層分析變數 |
使用套件 survival 中內建的資料 ovarian,此為子宮癌生存時間的資料集。
data("ovarian")
head(ovarian, 10)
## futime fustat age resid.ds rx ecog.ps
## 1 59 1 72.3315 2 1 1
## 2 115 1 74.4932 2 1 1
## 3 156 1 66.4658 2 1 2
## 4 421 0 53.3644 2 2 1
## 5 431 1 50.3397 2 1 1
## 6 448 0 56.4301 1 1 2
## 7 464 1 56.9370 2 2 2
## 8 475 1 59.8548 2 2 2
## 9 477 0 64.1753 2 1 1
## 10 563 1 55.1781 1 2 2
其中 futime 為生存或是資料不再更新(如刪除,不再追蹤)的時間,fustat 為是否有持續追蹤的指標(censoring status),age 為年齡,resid.ds 是否目前仍有疾病 (1為無,2為有),rx 為治療或控制組(1 為控制組 placebo, 2 為治療組 thiopeta),ecog.ps 為美國東岸癌症臨床研究合作組織定義之日常體能狀態(1 為較佳,分數越高越差)。
# the prototype of Surv
# time 為與時間並進的變數
# event 為指標,需考慮 type 為何;預設為 0 為存活,1 為死亡
# type 為 censoring 的型態,此會與 event 之值有關
Surv(time, time2, event,
type=c('right', 'left', 'interval', 'counting', 'interval2', 'mstate'))
# the prototype of coxph
# formula: 需注意先將應變數透過函式(Surv)轉為物件
# init: 反覆計算中使用的初始值向量,預設皆為 0
# control: 其他用於反覆計算之參數選項,可接受 coxph.control 定義之物件
# ties: 預設為 Efron,處理死亡時間更精確
# singular.ok: 如何處理模型矩陣中的共線性
# robust: 若為真,將可得到一穩定的變異(Variance)估計
coxph(formula, data, weights, subset,
na.action, init, control,
ties=c("efron","breslow","exact"),
singular.ok=TRUE, robust=FALSE,
model=FALSE, x=FALSE, y=TRUE, tt, ...)
# the prototype of coxph.control
coxph.control(eps = 1e-09, toler.chol = .Machine$double.eps^0.75,
iter.max = 20, toler.inf = sqrt(eps), outer.max = 10, timefix=TRUE)
ova.fit <- coxph(Surv(futime, fustat) ~ age + ecog.ps, data = ovarian)
ova.fit
## Call:
## coxph(formula = Surv(futime, fustat) ~ age + ecog.ps, data = ovarian)
##
## coef exp(coef) se(coef) z p
## age 0.1615 1.1753 0.0499 3.24 0.0012
## ecog.ps 0.0187 1.0188 0.5991 0.03 0.9751
##
## Likelihood ratio test=14.3 on 2 df, p=0.000787
## n= 26, number of events= 12
Cox regression 結果中顯示,coef 為變數 age 或 ecog.ps 的係數,exp(coef) 是一個生存比率,se(coef) 為係數的標準差,而 Z 表示 Z-score,P 為 P-value,可以透過 Z-score 來推求出 P-value。
# the prototype of cox.zph
# transform: 指定在驗證假設前將存活時間進行轉換的方法
# global: 除了單變數檢驗外,是否需要進行全域卡方檢驗
cox.zph(fit.model, transform="km", global=TRUE)
ova.test <- cox.zph(ova.fit, transform="km", global=TRUE)
print(ova.test)
## rho chisq p
## age -0.243 0.856 0.355
## ecog.ps 0.520 2.545 0.111
## GLOBAL NA 3.195 0.202
由上可以看出,以 age 與 ecog.ps 二變數的 Cox 模型,其模型擬合結果並不顯著。
plot(ova.test)
透過 coxph.detail 回傳許多計算細節,將有利於導入新的方法。
coxph.detail(ova.fit)
## $time
## [1] 59 115 156 268 329 353 365 431 464 475 563 638
##
## $means
## age ecog.ps
## 59 69.09819 1.455425
## 115 68.46900 1.544049
## 156 66.17359 1.751348
## 268 66.13888 1.721811
## 329 59.69610 1.507553
## 353 59.77545 1.509985
## 365 59.28316 1.439937
## 431 58.40780 1.596546
## 464 58.75868 1.583439
## 475 58.91087 1.548638
## 563 56.39392 1.688778
## 638 56.53567 1.652492
##
## $nevent
## [1] 1 1 1 1 1 1 1 1 1 1 1 1
##
## $nrisk
## [1] 26 25 24 23 22 21 20 17 15 14 12 11
##
## $hazard
## [1] 0.01207211 0.01442131 0.01991626 0.02228211 0.03944350 0.03963251
## [7] 0.04529802 0.06142322 0.06738846 0.07301832 0.12124602 0.13538256
##
## $score
## age ecog.ps
## 59 3.2333105 -0.4554246
## 115 6.0242037 -0.5440489
## 156 0.2922075 0.2486520
## 268 8.3652187 0.2781892
## 329 -16.5590971 -0.5075530
## 353 3.4437534 0.4900149
## 365 5.1415416 -0.4399369
## 431 -8.0681010 -0.5965458
## 464 -1.8216798 0.4165610
## 475 0.9439309 0.4513619
## 563 -1.2158159 0.3112218
## 638 0.2205275 0.3475083
##
## $imat
## , , 59
##
## age ecog.ps
## age 49.5808416 -0.4278646
## ecog.ps -0.4278646 0.2480130
##
## , , 115
##
## age ecog.ps
## age 56.798874 -0.1688140
## ecog.ps -0.168814 0.2480597
##
## , , 156
##
## age ecog.ps
## age 59.34410 1.4915098
## ecog.ps 1.49151 0.1868242
##
## , , 268
##
## age ecog.ps
## age 66.382212 1.659029
## ecog.ps 1.659029 0.200800
##
## , , 329
##
## age ecog.ps
## age 22.1041739 -0.2359377
## ecog.ps -0.2359377 0.2499430
##
## , , 353
##
## age ecog.ps
## age 20.8898416 -0.2775354
## ecog.ps -0.2775354 0.2499003
##
## , , 365
##
## age ecog.ps
## age 21.9383999 -0.5929218
## ecog.ps -0.5929218 0.2463924
##
## , , 431
##
## age ecog.ps
## age 21.4326674 -0.2817995
## ecog.ps -0.2817995 0.2406789
##
## , , 464
##
## age ecog.ps
## age 21.4157990 -0.3733844
## ecog.ps -0.3733844 0.2430379
##
## , , 475
##
## age ecog.ps
## age 22.9045464 -0.3358857
## ecog.ps -0.3358857 0.2476343
##
## , , 563
##
## age ecog.ps
## age 19.3536405 0.9661201
## ecog.ps 0.9661201 0.2143628
##
## , , 638
##
## age ecog.ps
## age 21.417710 1.1280254
## ecog.ps 1.128025 0.2267463
##
##
## $varhaz
## [1] 0.0001457358 0.0002079742 0.0003966576 0.0004964923 0.0015557897
## [6] 0.0015707358 0.0020519106 0.0037728117 0.0045412045 0.0053316755
## [11] 0.0147005982 0.0183284376
##
## $y
## time status
## 1 -1 59 1
## 2 -1 115 1
## 3 -1 156 1
## 22 -1 268 1
## 23 -1 329 1
## 24 -1 353 1
## 25 -1 365 1
## 26 -1 377 0
## 4 -1 421 0
## 5 -1 431 1
## 6 -1 448 0
## 7 -1 464 1
## 8 -1 475 1
## 9 -1 477 0
## 10 -1 563 1
## 11 -1 638 1
## 12 -1 744 0
## 13 -1 769 0
## 14 -1 770 0
## 15 -1 803 0
## 16 -1 855 0
## 17 -1 1040 0
## 18 -1 1106 0
## 19 -1 1129 0
## 20 -1 1206 0
## 21 -1 1227 0
##
## $x
## age ecog.ps
## 1 72.3315 1
## 2 74.4932 1
## 3 66.4658 2
## 22 74.5041 2
## 23 43.1370 1
## 24 63.2192 2
## 25 64.4247 1
## 26 58.3096 1
## 4 53.3644 1
## 5 50.3397 1
## 6 56.4301 2
## 7 56.9370 2
## 8 59.8548 2
## 9 64.1753 1
## 10 55.1781 2
## 11 56.7562 2
## 12 50.1096 1
## 13 59.6301 2
## 14 57.0521 1
## 15 39.2712 1
## 16 43.1233 2
## 17 38.8932 2
## 18 44.6000 1
## 19 53.9068 1
## 20 44.2055 1
## 21 59.5890 2
經典的存活分析建立在等比例風險假設(Proportional hazard assumption, PH assumption)。但當風險因子會隨著時間改變時,原本的 Cox 迴歸模型就需要修正,其中最常使用的便是分層 Cox 迴歸模型。分層 Cox 迴歸模型將這些不符合等比例風險假設的因子當作分層變數,表示不同層的基礎危險函式(baseline hazard function)是不同的,但需注意分層數若太多可能會降低統計檢定力(statistical power)。在 R 實作中可透過函式 strata 針對某一變數進行分層分析。
strata.data <- data.frame(
time = c(4,3,1,1,2,2,3),
status = c(1,1,1,0,1,1,0),
x = c(0,2,1,1,1,0,0),
sex = c(0,0,0,0,1,1,1)
)
summary(coxph(Surv(time,status) ~ x + strata(sex), data=strata.data))
## Call:
## coxph(formula = Surv(time, status) ~ x + strata(sex), data = strata.data)
##
## n= 7, number of events= 5
##
## coef exp(coef) se(coef) z Pr(>|z|)
## x 0.8023 2.2307 0.8224 0.976 0.329
##
## exp(coef) exp(-coef) lower .95 upper .95
## x 2.231 0.4483 0.4451 11.18
##
## Concordance= 0.667 (se = 0.362 )
## Rsquare= 0.144 (max possible= 0.669 )
## Likelihood ratio test= 1.09 on 1 df, p=0.2971
## Wald test = 0.95 on 1 df, p=0.3293
## Score (logrank) test = 1.05 on 1 df, p=0.3053