參考教程:http://www.sthda.com/english/wiki/survival-analysis-basics
假設(shè)有228個被診斷患有肺癌的病人開始長期的隨訪盆繁,如果病人死亡腺劣;則隨訪結(jié)束怕午,并記錄生存時間(從確診到死亡的時間)。而生存分析Survival Analysis 主要回答三個方面的問題:
(1)病人的第5年生存率是多少震贵?病人總體的中位生存率的時間可以到多久?
(2)若根據(jù)病人信息(例如性別)利赋,將病人分為兩組,那么這兩組的生存率是否有顯著差異猩系?
(3)若有很多病人的臨床信息或者分子特征媚送,其中哪些屬性會顯著影響病人的生存?
1寇甸、基本概念
1.1 event事件與survival time生存時間
- 在生存分析中塘偎,這里的事件一般是指死亡,在廣義的生存分析中拿霉,事件可以引申至許多其它含義吟秩,例如疾病復(fù)發(fā)等;
如果處理TCGA的數(shù)據(jù)绽淘,會發(fā)現(xiàn)有各種各樣的event的定義涵防,可以參考筆記http://www.reibang.com/p/f07588bcf22e。本文筆記全篇采用的是死亡作為事件收恢。
- 而生存時間是指在事件發(fā)生的前提下武学,從病人確診到死亡的時間。
1.2 Censor 刪失值
- 在隨訪的過程中伦意,可能無法全部病人都可以收集到準(zhǔn)確地生存時間火窒。
- 一方面由于隨訪項目時間限制,直至隨訪結(jié)束驮肉,病人仍在世熏矿;一方面可能在隨訪期間,病人失聯(lián)离钝、或者因其它原因去世等票编,無法繼續(xù)隨訪。
-
這樣的數(shù)據(jù)就稱之為Censor卵渴,而此時的生存時間即為所能記錄到的最長生存時間慧域。病人的status要么是事件發(fā)生了,要么就是Censor浪读。
2昔榴、Kaplan-Meier與Log-rank test
2.1方法簡介
- Kaplan-Meier簡單來說是根據(jù)病人的status與survival time計算、預(yù)估病人在確診后時間t時刻的生存率(survival probability)如何碘橘。
survivor function關(guān)注的是event事件不發(fā)生的概率互订;與之相反,之后會提到的hazard function則主要關(guān)注event事件發(fā)生的概率
- Log-rank test是指將病人分為兩組或者多組的情況下痘拆,組間的生存率是否有顯著差異仰禽。
一般上述二者同時分析
2.2 分析R包與示例數(shù)據(jù)
- R包
# install.packages(c("survival", "survminer"))
library("survival") #生存分析
library("survminer") #結(jié)果可視化
- 示例數(shù)據(jù)
lung {survival}
head(lung)
# inst time status age sex ph.ecog ph.karno pat.karno meal.cal wt.loss
# 1 3 306 2 74 1 1 90 100 1175 NA
# 2 3 455 2 68 1 0 90 90 1225 15
# 3 3 1010 1 56 1 0 90 90 NA 15
# 4 5 210 2 57 1 1 90 60 1150 11
# 5 1 883 2 60 1 0 100 90 NA 0
# 6 12 1022 1 74 1 1 50 80 513 0
# inst: Institution code
# time: Survival time in days(*) 生存時間
# status: censoring status 1=censored, 2=dead(*) 事件是否發(fā)生
# age: Age in years
# sex: Male=1 Female=2
# ph.ecog: ECOG performance score (0=good 5=dead)
# ph.karno: Karnofsky performance score (bad=0-good=100) rated by physician
# pat.karno: Karnofsky performance score as rated by patient
# meal.cal: Calories consumed at meals
# wt.loss: Weight loss in last six months
如果挖掘TCGA的數(shù)據(jù),通常
0
表示存活纺蛆,1
表示死亡
2.3 survival
分析
- 開始分析:按性別將病人分為兩組
fit <- survfit(Surv(time, status) ~ sex, data = lung)
print(fit)
# Call: survfit(formula = Surv(time, status) ~ sex, data = lung)
#
# n events median 0.95LCL 0.95UCL
# sex=1 138 112 270 212 310
# sex=2 90 53 426 348 550
如上吐葵,n
表示每組的病人數(shù);events
表示每組有多少病人死亡桥氏;median
表示中位生存率所對應(yīng)的生存時間折联;最后兩列表示第三列的95%置信區(qū)間。
res.sum <- surv_summary(fit)
head(res.sum[res.sum$sex==1,])
# time n.risk n.event n.censor surv std.err upper lower strata sex
# 1 11 138 3 0 0.9782609 0.01268978 1.0000000 0.9542301 sex=1 1
# 2 12 135 1 0 0.9710145 0.01470747 0.9994124 0.9434235 sex=1 1
# 3 13 134 2 0 0.9565217 0.01814885 0.9911586 0.9230952 sex=1 1
# 4 15 132 1 0 0.9492754 0.01967768 0.9866017 0.9133612 sex=1 1
# 5 26 131 1 0 0.9420290 0.02111708 0.9818365 0.9038355 sex=1 1
# 6 30 130 1 0 0.9347826 0.02248469 0.9768989 0.8944820 sex=1 1
head(res.sum[res.sum$sex==2,])
# time n.risk n.event n.censor surv std.err upper lower strata sex
# 120 5 90 1 0 0.9888889 0.01117336 1.0000000 0.9674682 sex=2 2
# 121 60 89 1 0 0.9777778 0.01589104 1.0000000 0.9477934 sex=2 2
# 122 61 88 1 0 0.9666667 0.01957401 1.0000000 0.9302835 sex=2 2
# 123 62 87 1 0 0.9555556 0.02273314 0.9990942 0.9139143 sex=2 2
# 124 79 86 1 0 0.9444444 0.02556550 0.9929738 0.8982868 sex=2 2
# 125 81 85 1 0 0.9333333 0.02817181 0.9863173 0.8831956 sex=2 2
- 如上好像沒有看到
log-rank test
的結(jié)果识颊,即組間生存率差異的顯著性诚镰。其實參看下面的可視化結(jié)果是有的,如果想提取出來P值的內(nèi)容祥款,可以如下操作:
surv_diff <- survdiff(Surv(time, status) ~ sex, data = lung)
# Call:
# survdiff(formula = Surv(time, status) ~ sex, data = lung)
#
# N Observed Expected (O-E)^2/E (O-E)^2/V
# sex=1 138 112 91.6 4.55 10.3
# sex=2 90 53 73.4 5.68 10.3
#
# Chisq= 10.3 on 1 degrees of freedom, p= 0.001
#雖然如上結(jié)果是有P值的清笨,但是嘗試之后發(fā)現(xiàn)從對象中只能提取chisq的值,然后再進一步轉(zhuǎn)換
p.val = 1 - pchisq(surv_diff$chisq, length(surv_diff$n) - 1)
p.val
# [1] 0.001311165
2.4 survminer
結(jié)果可視化
(1)生存曲線
ggsurvplot(fit,
pval = TRUE, conf.int = TRUE,
risk.table = TRUE)
圖釋
上圖表示:時間對應(yīng)的生存率的生存曲線圖刃跛,曲線中的短豎線表示在時間點有缺失值病人抠艾。不同顏色表示不同分組,陰影部分表示95%置信區(qū)間桨昙;左下角p值表示基于log-rank test計算得到的P值检号,對于本圖的結(jié)果p=0.0013腌歉,即不同性別的生存率有顯著差異。
下面的表:不同時間點對應(yīng)每組尚未發(fā)生事件(死亡)的數(shù)目齐苛。
圖形參數(shù)(結(jié)合具體代碼理解)
p1=ggsurvplot(fit,
pval = TRUE, conf.int = TRUE,
risk.table = TRUE, # Add risk table
risk.table.col = "strata", # Change risk table color by groups
linetype = "strata", # Change line type by groups
surv.median.line = "hv", # Specify median survival
ggtheme = theme_bw(), # Change ggplot2 theme
palette = c("#E7B800", "#2E9FDF"))
p2=ggsurvplot(
fit, # survfit object with calculated statistics.
pval = TRUE, # show p-value of log-rank test.
conf.int = TRUE, # show confidence intervals for
# point estimaes of survival curves.
conf.int.style = "step", # customize style of confidence intervals
xlab = "Time in days", # customize X axis label.
break.time.by = 200, # break X axis in time intervals by 200.
ggtheme = theme_light(), # customize plot and risk table with a theme.
risk.table = "abs_pct", # absolute number and percentage at risk.
risk.table.y.text.col = T,# colour risk table text annotations.
risk.table.y.text = FALSE,# show bars instead of names in text annotations
# in legend of risk table.
ncensor.plot = TRUE, # plot the number of censored subjects at time t
surv.median.line = "hv", # add the median survival pointer.
legend.labs =
c("Male", "Female"), # change legend labels.
palette =
c("#E7B800", "#2E9FDF") # custom color palettes.
)
arrange_ggsurvplots(list(p1,p2))
(2)其它類型曲線
- 參數(shù)
fun="event"
翘盖,表示cumulative event事件累計發(fā)生率
p3=ggsurvplot(fit,
conf.int = TRUE,
risk.table.col = "strata", # Change risk table color by groups
ggtheme = theme_bw(), # Change ggplot2 theme
palette = c("#E7B800", "#2E9FDF"),
fun = "event")
- 參數(shù)
fun="cumhaz"
,表示cummulative hazard表示累計風(fēng)險水平(在時刻t凹蜂,事件發(fā)生的可能性)
p4=ggsurvplot(fit,
conf.int = TRUE,
risk.table.col = "strata", # Change risk table color by groups
ggtheme = theme_bw(), # Change ggplot2 theme
palette = c("#E7B800", "#2E9FDF"),
fun = "cumhaz")
arrange_ggsurvplots(list(p3,p4))
3馍驯、Cox Proportional-Hazards Model比例風(fēng)險模型
3.1 簡單理解
- 上面了解的log-rank test用于比較兩個分組的生存率是否有顯著差異,從而反映出這個分組因子的意義玛痊。但由于必須要分組汰瘫,所以必須使用分類變量,或者將連續(xù)變量(基因表達)轉(zhuǎn)為分組變量(中位數(shù)劃分)擂煞。
- 而這里的Cox Proportional-Hazards Model可以理解為回歸模型混弥。其中回歸模型的響應(yīng)變量Y是Hazard rate(風(fēng)險因子,可以類比死亡率)对省;而預(yù)測變量就是想驗證是否會影響病人生存率的臨床特征剑逃、基因表達等變量(分類變量、連續(xù)變量均可)官辽。通過P值反映變量是否有顯著影響蛹磺;通過變量的系數(shù)coefficient表征如何影響Hazard rate,更常用的形式為:Hazard ratio(HR)=exp(coef)同仆;如果HR<1(coef<0)萤捆,則表明該變量越大,風(fēng)險越低俗批,生存率越高俗或;HR>1(coef>0),則表明該變量越大岁忘,風(fēng)險越高辛慰,生存率越小。
3.2 單變量Cox回歸
res.cox <- coxph(Surv(time, status) ~ sex, data = lung)
res.cox
# Call:
# coxph(formula = Surv(time, status) ~ sex, data = lung)
#
# coef exp(coef) se(coef) z p
# sex -0.5310 0.5880 0.1672 -3.176 0.00149
#
# Likelihood ratio test=10.63 on 1 df, p=0.001111
# n= 228, number of events= 165
exp(res.cox$coefficients)
# sex
# 0.5880028
- 對多個變量分別進行單變量Cox回歸
#分別回歸
covariates <- c("age", "sex", "ph.karno", "ph.ecog", "wt.loss")
univ_formulas <- sapply(covariates,
function(x) as.formula(paste('Surv(time, status)~', x)))
univ_models <- lapply( univ_formulas, function(x){coxph(x, data = lung)})
#提取各個變量的回歸結(jié)果
univ_results <- lapply(univ_models,
function(x){
x <- summary(x)
p.value<-signif(x$wald["pvalue"], digits=2)
wald.test<-signif(x$wald["test"], digits=2)
beta<-signif(x$coef[1], digits=2);#coeficient beta
HR <-signif(x$coef[2], digits=2);#exp(beta)
HR.confint.lower <- signif(x$conf.int[,"lower .95"], 2)
HR.confint.upper <- signif(x$conf.int[,"upper .95"],2)
HR <- paste0(HR, " (",
HR.confint.lower, "-", HR.confint.upper, ")")
res<-c(beta, HR, wald.test, p.value)
names(res)<-c("beta", "HR (95% CI for HR)", "wald.test",
"p.value")
return(res)
#return(exp(cbind(coef(x),confint(x))))
})
res <- t(as.data.frame(univ_results, check.names = FALSE))
as.data.frame(res)
# beta HR (95% CI for HR) wald.test p.value
# age 0.019 1 (1-1) 4.1 0.042
# sex -0.53 0.59 (0.42-0.82) 10 0.0015
# ph.karno -0.016 0.98 (0.97-1) 7.9 0.005
# ph.ecog 0.48 1.6 (1.3-2) 18 2.7e-05
# wt.loss 0.0013 1 (0.99-1) 0.05 0.83
3.3 多變量Cox回歸(多元回歸)
res.cox <- coxph(Surv(time, status) ~ age + sex + ph.ecog, data = lung)
summary(res.cox)
# Call:
# coxph(formula = Surv(time, status) ~ age + sex + ph.ecog, data = lung)
#
# n= 227, number of events= 164
# (因為不存在干像,1個觀察量被刪除了)
#
# coef exp(coef) se(coef) z Pr(>|z|)
# age 0.011067 1.011128 0.009267 1.194 0.232416
# sex -0.552612 0.575445 0.167739 -3.294 0.000986 ***
# ph.ecog 0.463728 1.589991 0.113577 4.083 4.45e-05 ***
# ---
# Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
#
# exp(coef) exp(-coef) lower .95 upper .95
# age 1.0111 0.9890 0.9929 1.0297
# sex 0.5754 1.7378 0.4142 0.7994
# ph.ecog 1.5900 0.6289 1.2727 1.9864
#
# Concordance= 0.637 (se = 0.025 )
# Likelihood ratio test= 30.5 on 3 df, p=1e-06
# Wald test = 29.93 on 3 df, p=1e-06
# Score (logrank) test = 30.5 on 3 df, p=1e-06
ggforest(res.cox, data = lung,
main = "Hazard ratio",
cpositions = c(0.10, 0.22, 0.4),
fontsize = 1.0)
3.4 注意點
(1)如果多變量cox回歸結(jié)果證明多個變量均影響Hazard rate帅腌,那么當(dāng)想要觀察其中一個變量所造成分組的生存率差異(KM plot)時,需要其它變量的值拉到統(tǒng)一水平(均值)
(2)Cox回歸一個重要的假設(shè)麻汰,就是變量對于hazard rate的影響不隨時間的變化而變化(等比例)速客,可通過統(tǒng)計方法檢驗變量數(shù)據(jù)是否適合Cox回歸分析。詳見 http://www.sthda.com/english/wiki/cox-model-assumptions