14 Survival analysis
ในงานวิจัยที่กระทำกับผู้ป่วย หรือแม้กระทั้งเซลล์นั้น บางครั้งจะมีความจำเป็นที่ต้องทำการวิเคราะห์ข้อมูลเพื่อเปรียบเทียบสร้างแบบจำลองที่สามารถทำนายเวลาที่ใช้ก่อนที่จะเกิดเหตุการณ์ที่ท่านสนใจ (Event) เช่น เวลาที่ผู้ป่วยจะเสียชีวิตจากโรคมะเร็งนับตั้งแต่วันวินิจฉัย เวลาของเซลล์ที่จะตายหลังจากใส่สารบางอย่างที่สนใจ เป็นต้น
ลักษณะพิเศษของการวิเคราะห์ Survival analysis คือ มีการวิเคราะห์โดยใช้ปัจจัยที่เรียกว่า Censoring ร่วม ซึ่งคือการที่ เหตุการณ์ที่คาดหวังว่าจะเกิดนั้นไม่มาถึงแม้ว่าจะครบตามเวลาที่ผู้วิจัยสังเกตการณ์แล้ว ซึ่งทำให้ไม่สามารถมั่นใจได้ว่าเหตุการณ์นั้นจะเกิดต่อไปหรือไม่ ณ เวลาหลังจากนี้
การ Censor โดยหลักมี 3 แบบ คือ
Right-censor (ดังรูป) คือ ไม่แน่ใจข้อมูลการเกิด event เวลาสุดท้ายที่พบ ซึ่งพบมากที่สุด
Left-censor คือ ไม่แน่ใจข้อมูลช่วงเวลาเริ่มต้น เช่น Diagnosis วันไหน
Interval-censor คือ เวลาช่วงใดช่วงหนึ่งหายไป
14.1 Kaplein-Meier estimate (KM)
คือ กราฟแสดงอัตราการเกิดของเหตุการณ์เมื่อเทียบกับเวลาที่ผ่านไป โดยหลักการคำนวณ Survival คือ
\[ \hat{S}(t) = \prod_{i: t_{i} \leq t}(1- \frac{d_{i}}{n_{i}})\]
\[ \text{Survival proability} = \frac{n.risk - n.event}{n.risk} \]
อธิบายหลักการอย่างง่ายของ KM นั่นคือ ทุกเคสทียังไม่เกิดเหตุการณ์นั้น จะเป็น เคสที่เสี่ยงต่อการเกิดเหตุการณ์ (At risk) ซึ่งจำนวนเคสแรกเริ่มที่เสี่ยง (Number at risk) จะเท่ากับจำนวนเคสทั้งหมด (Sample size) โดยจะนับการเกิด Event ตามปกติ เพียงแต่ถ้าเคสนั้นถูก Censor นั้น n.risk
จะลดลงด้วย ทำให้อัตราการเกิด Event ยังไม่เปลี่ยนแปลง ดังตัวอย่างตามตาราง
time | n.risk | n.event | n.censor | calculation | estimate |
---|---|---|---|---|---|
5 | 10 | 1 | 0 | 9/10 | 0.9 |
11 | 9 | 3 | 0 | 0.9 x 6/9 | 0.6 |
12 | 6 | 1 | 0 | 0.6 x 5/6 | 0.5 |
92 | 5 | 0 | 1 | 0.5 x 5/5 | 0.5 |
105 | 4 | 0 | 1 | 0.5 x 4/4 | 0.5 |
173 | 3 | 0 | 1 | 0.5 x 3/3 | 0.5 |
174 | 2 | 0 | 1 | 0.5 x 2/2 | 0.5 |
175 | 1 | 0 | 1 | 0.5 x 0/1 | 0 |
เมื่อนำไปพล็อตกราฟแล้วจะได้ผลดังนี้
สังเกตุว่าส่วนที่ Censor (มีสัญลักษณ์ +
) จะไม่มีการตกลงของกราฟ แต่เมื่อถึงเวลาที่มี Event เกิดขึ้น การตกลงของกราฟจะสูงกว่าเมื่อไม่มี Censor นำมาก่อน
14.1.1 การสร้าง KM ใน R
ตัวอย่างข้อมูลของผู้ป่วยมะเร็งรังไข่ที่ได้รับการรักษาโดยการผ่าตัด
## [1] "futime" "fustat" "age" "resid.ds" "rx" "ecog.ps"
อธิบายตัวแปร:
age
= อายุfutime
= ระยะเวลาติดตามตั้งแต่วินิจฉัยจนเสียชีวิต/มาพบแพทย์ครั้งสุดท้ายfustat
= 0 - censor, 1 - deadresid.ds
= มีชิ้นส่วนของมะเร็งหลงเหลือหลังจากการผ่าตัด (ผ่าตัดได้ไม่หมด)rx
= กลุ่มการรักษาecog.ps
= ECOG performance status คะแนนน้อยแปลว่าผู้ป่วยมีสุขภาพโดยรวมดี
เมื่อใช้ Function Surv()
จะทำการเปลี่ยน futime
ให้รับรู้การ Censor สังเกตว่าผู้ป่วยที่ ไม่เกิดเหตุการณ์จะมีสัญลักษณ์ +
อยู่ข้างหลัง บ่งบอกว่าข้อมูลนั้นถูก Censor นั่นหมายความว่า ผู้ป่วยจะเกิดเหตุการณ์หรือไม่ก็ได้หลังจากนี้ เพียงแต่ผู้วิจัยไม่สามารถทราบได้แล้ว
censored_df <- ovarian |>
mutate(censored_futime = Surv(ovarian$futime, ovarian$fustat))
head(select(censored_df, futime, fustat, censored_futime))
การพล็อต KM นั้นสามารถทำได้โดยใช้ Package survminer
โดยเริ่มจากการสร้างตาราง Survival curve จากคำสั่ง survfit()
library(survminer)
ovarian_surv <- survfit(
Surv(futime/365.25, fustat) ~ 1, data = ovarian # เปลี่ยนเป็นปี
)
ovarian_surv |> tidy() |> head(10)
หลังจากนั้นใช้คำสั่ง ggsurvplot()
เพื่อทำการสร้างกราฟ
ggsurvplot(ovarian_surv, risk.table = TRUE, break.time.by = 0.25,
surv.median.line = "hv")
จะเห็นว่าผู้ป่วยกลุ่มนี้มี Median survival อยู่ประมาณ 1.75 ปี
ovarian_surv_resid <- survfit(
Surv(futime/365.25, fustat) ~ resid.ds, data = ovarian
)
ggsurvplot(ovarian_surv_resid, risk.table = TRUE, break.time.by = 0.25,
surv.median.line = "hv", pval = TRUE)
จะพบว่า ถ้าผ่าตัดแล้วไม่เหลือร่องรอยของโรค จะมีอัตราการรอดชีวิตที่ดีกว่า แต่ยังไม่ถึงระดับมีนัยสำคัญ
14.2 Log-rank test
Log-rank test คือ Non-parametric test สำหรับ Univariate analysis ที่เปรียบเทียบความแตกต่างของอัตราการเกิด Event ว่าแตกต่างอย่างมีนัยสำคัญหรือไม่
ovarian_surv_diff <- survdiff(
Surv(futime/365.25, fustat) ~ resid.ds, data = ovarian
)
ovarian_surv_diff
## Call:
## survdiff(formula = Surv(futime/365.25, fustat) ~ resid.ds, data = ovarian)
##
## N Observed Expected (O-E)^2/E (O-E)^2/V
## resid.ds=1 11 3 6.26 1.70 3.62
## resid.ds=2 15 9 5.74 1.85 3.62
##
## Chisq= 3.6 on 1 degrees of freedom, p= 0.06
Observed
คือ จำนวน event ที่เกิดขึ้นในแต่ละกลุ่มExpected
คือ จำนวน event ที่คาดว่าจะเกิดขึ้นในแต่ละกลุ่ม(O-E)^2/E
= Chi-square statistics ของค่า observed และ expectedChisq
= ผลสุดท้ายของ Chi-square statistics =sum(O-E)^2/E
p
= p-value ของ Chi-square statistics
ค่า Log-rank นี้ สามารถแสดงใน KM ได้โดยใช้ pval
= TRUE
ตามหัวข้อเบื้องต้น
14.3 Cox-proportional hazard (CPH) model
คือ Semi-parametric model ซึ่งวัด Risk ของการเกิด Event นั้นๆ โดยมีสมการ คือ
\[ h(t) = h_{0}(t) \times exp(b_{1}X_{1} + b_{2}X_{2}+ ... + b_{s}X_{p}) \]
\[ ln(\frac{h(t)}{h_{0}(t)}) = b_{1}X_{1} + b_{2}X_{2}+ ... + b_{s}X_{p} \]
ซึ่ง \(h(t)/h_{0}(t)\) นั้นคือ Hazard ratio (HR) หรือ ความเสี่ยงของการเกิด event นั้นๆ
การวิเคราะห์ CPH นั้นมีข้อดีกว่า Log-rank คือสามารถประมาณการเชิงปริมาณ (Quantitative measurement) ผ่าน HR และสามารถวิเคราะห์สมการแบบ Multivariate analysis ได้
ovarian_cox <- coxph(Surv(futime/365.25, fustat) ~
resid.ds + age + factor(rx), data = ovarian)
ovarian_cox
## Call:
## coxph(formula = Surv(futime/365.25, fustat) ~ resid.ds + age +
## factor(rx), data = ovarian)
##
## coef exp(coef) se(coef) z p
## resid.ds 0.6964 2.0065 0.7585 0.918 0.35858
## age 0.1285 1.1372 0.0473 2.718 0.00657
## factor(rx)2 -0.8489 0.4279 0.6392 -1.328 0.18416
##
## Likelihood ratio test=16.77 on 3 df, p=0.0007889
## n= 26, number of events= 12
exp(coef)
= HR = \(h(t)/h_{0}(t)\) ในที่นี้ท่านสามารถอภิปรายได้ว่า อายุที่เพิ่มขึ้น 1 ปีนั้น ส่งผลให้เกิดอัตราการเสียชีวิตในผู้ป่วยมะเร็งรังไข่เพิ่มขึ้น 1.13 เท่า (13%) และมีนัยสำคัญทางสถิติp
ในตาราง คือ ค่าคำนวณ \(p\)-value จาก Wald’s test ของแต่ละตัวแปรว่ามีผลต่ออัตราการรอดชีวิตหรือไม่p
ข้างล่าง คือ overall \(p\) จาก Likelihood ratio test ว่าจากทั้งหมด มีตัวแปรใดตัวแปรหนึ่งส่งผลให้อัตรากการรอดชีวิตเปลี่ยนไปอย่างมีนัยสำคัญทางสถิติหรือไม่
14.3.1 การตรวจสอบ Assumption validity ของ CPH
CPH นั้นมี Assumption ดังนี้:
ตัวแปรแต่ละกลุ่มมีอัตราการเกิด Event ที่แตกต่างกัน
HR เท่ากันทุกช่วงเวลา เช่น ที่ 1, 2, 5 ปี อัตราส่วนการเสียชีวิตระหว่างตัวแปรเท่ากันหมด
ตัวแปรมีความสัมพันธ์แบบ Linear continuous variable
ไม่จำเป็นต้องทราบลักษณะการกระจายตัวของข้อมูลก่อน (จึงเป็น Semi-parametric model)
สามารถตรวจสอบ HR ได้โดยใช้ Proportionality assumption test จาก Schoenfeld residuals โดย cox.zph()
โดยการทดสอบนี้ จะทำการเปรียบเทียบ Residuals ระหว่าง Risk-weight average กับ ตัวแปรนั้นๆ ว่ามีการเปลี่ยนแปลงไปในทิศทางใดทิศทางหนึ่งหรือไม่ ถ้ามี (\(p\) < 0.05) หมายความว่า เวลาที่ผ่านไปอาจจะส่งผลให้ HR นั้นมีความแตกต่างกัน ซึ่งจะต้องทำ Time-varying CPH เพิ่มเติม
โดยในข้อมูล ovarian
นี้ ไม่มีตัวใดที่ \(p\)-value < 0.05 จึงถือได้ว่า อัตราส่วนนั้นคงที่ และทำให้ CPH นั้น Valid
ในส่วนของ Linearity สามารถตวจสอบโดยใช้ ggcoxfunctional()
ovarian_linear_age <- ggcoxfunctional(Surv(futime/365.25, fustat) ~ age + + I(log(age)) + I(sqrt(age)), data = ovarian)
ovarian_linear_age
จะเห็นว่า age
นั้นการเพิ่มขึ้นแบบ Linearity โดยมี Deviation เล็กน้อย