教小高改bug

  博客园 :: 首页 :: 博问 :: 闪存 :: :: 联系 :: :: 管理 ::

生存分析:将事件的结果(终点事件)和出现这一结果所经历的时间结合起来的一种统计分析方法。

生存分析的目的:
1.生存率比较:估计处理组和对照组n年的生存率和中位生存期。
2.生存曲线比较:比较处理组和对照组的生存率是否有差别。
3.影响因素分析:分析变量与生存结局/事件的关系。
4.生存预测:根据变量预测患者n年的生存率。

从生存分析的方法上看,一般可以分为三类:
1.参数法:知道生存时间的分布模型,然后根据数据来估计模型参数,最后以分布模型来计算生存率。如Weibull回归、lognormal回归等。一般不用,因为目前认为我们不知道生存时间符合什么模型。
2.非参数法:不需要生存时间分布,根据样本统计量来估计生存率。常见方法Kaplan-Meier分析(乘积极限法)、寿命法(Life Tables)。而对于Kaplan-Meier法来说,其中的p值我们常用log-rank检验(对数秩检验)和Wilcoxon检验去求。
3.半参数法:也不需要生存时间的分布,但最终是通过模型来评估影响生存率的因素。最为常见的是Cox比例风险回归模型。

从生存分析的因素上看,有单因素分析和多因素分析:
1.单因素生存分析:描述生存过程。 常用的单因素分析方法有乘积极限法(Kaplan-Meier分析)和寿命表法(Life Tables)。
2.多因素生存分析:分析生存过程的影响因素。常用的多因素生存分析方法有Cox比例风险回归模型

在简单生存分析中,由于仅考虑单个影响因素(且为分类型或顺序型变量),故采取的是直接绘制生存曲线并作Log-Rank检验来判断影响因素和生存概率的方法。
而在Cox回归分析中,需要同时考虑多个影响因素(可为分类/顺序型变量,也可为数值型变量),故而绘制生存曲线的方式显然不合适,此时就需通过建模的方法来进一步分析。

单个变量的Cox回归和K-M法结果不一致时,此时我们还是应该选择Cox的结果,因为参数检验效力高于非参数检验。
多个变量的Cox回归中单个变量的显著性与K-M法不一致,此时我们应该选择cox的结果,因为K-M发只考虑单个变量,而Cox考虑了多个变量。

描述性统计分析:Kaplan-Meier分析:非参数估计,不要求总体的分布形式,直观地表现出两组或多组的生存率或死亡率,适合在文章中展示。
统计推断:组间比较:log-rank检验,两组之间生存率的差异是否显著。


Kaplan-Meier analysis 单因素生存分析绘图  KM-Plot  

rm(list = ls())
library(survival)
library(survminer)
library(pbapply)
setwd("D:/BioInformationAnalyze/TCGAdata/CRC")
load("TCGA-COAD_04.lncRNA_SurvData.Rdata")  # 生存分析输入数据,包含tpm形式的表达矩阵和临床信息

需要的文件有基因表达文件(exprSet)和生存数据文件(meta),文件格式如下:

年龄

sfit <- survfit(Surv(time, event) ~ age_group, data = meta)
              # Surv()函数创建生存数据对象(主要输入生存时间和状态逻辑值)
      # survfit()函数对生存数据对象拟合生存函数,创建KM(Kaplan-Meier)生存曲线
                   # time表示总生存期
                         # event表示终点事件,1死亡,0存活。
                                # ~age_group表示以年龄分组绘图,注意此方法仅适用二分类变量进行分组。如果不想分组,只看总体,~1即可
# 如果想看整体的sfit结果,可以summary(sfit) 或 summary(sfit)$table,
# 想看每个时间点的更好的方式则是:surv_summary(sfit):
                               # time:曲线上的时间点。
                               # n.risk:时间t时面临风险的受试者数量.
                               # n.event:在时间t发生的事件数。
                               # n.censor:在时间t时退出风险集且没有事件的受审查对象的数量。
                               # surv:生存概率的估计。
                               # std.err:生存的标准误差。
                               # upper:置信区间的上限。
                               # lower:置信区间的下限。
                               # strata:表示生存曲线的分层。如果分层不为 NULL,则结果中存在多条曲线。分层(因子)的水平是曲线的标签。
# 根据上述sfit结果,我们可以将KM生存数据进行可视化,主要使用Survminer包的ggsurvplot()函数:
ggsurvplot(sfit, conf.int = FALSE, pval = TRUE)
# 通过设置参数,可在生存曲线基础上,再绘制两张辅助图:
ggsurvplot(sfit, 
           palette = c("#E7B800", "#2E9FDF"),
           pval = TRUE, conf.int = TRUE,  # 显示p值和置信区间
           xlab = "Time in months",  # x轴标签
           linetype = "strata",  # 线条类型
         # fun = "event",  # 绘制cumulative events图,即事件发生累计概率图
           ggtheme = theme_light(),  # 更改 ggplot2 主题
           surv.median.line = "hv",  # 指定中位生存期
           risk.table = TRUE,  # Number at risk图,表示在该生存时间长度内,还存活的case;较直接得反映出两组的一个差异情况。
         # risk.table.col = "strata",  # 按分组改变risk table的颜色
           ncensor.plot = TRUE)  # Number of censoring图,即该时间段内的删失值。

性别、年龄

sfit1 <- survfit(Surv(time, event) ~ gender, data = meta)
sfit2 <- survfit(Surv(time, event) ~ age_group, data = meta)
splots <- list()
splots[[1]] <- ggsurvplot(sfit1, pval = TRUE, data = meta, risk.table = TRUE)
splots[[2]] <- ggsurvplot(sfit2, pval = TRUE, data = meta, risk.table = TRUE)
arrange_ggsurvplots(splots, print = TRUE, ncol = 2, nrow = 1, risk.table.height = 0.4)  # 内置拼图函数

单个基因

设定某一基因的表达基准,将临床样本分为高表达high与低表达low两组,再进行生存分析。这里用表达矩阵的tpm值进行计算。

g <- rownames(exprSet)[2]  # 挑选基因,可修改成自己感兴趣的基因
meta$gene <- ifelse(as.integer(exprSet[g,]) > median(as.integer(exprSet[g,])), "high", "low")
sfit1 <- survfit(Surv(time, event) ~ gene, data = meta)
ggsurvplot(sfit1, pval = TRUE, data = meta, risk.table = TRUE)

 多个基因

gs <- rownames(exprSet)[1:4]  # 挑选基因,可修改成自己感兴趣的基因
splots <- pblapply(gs, function(g){
  meta$gene <- ifelse(as.integer(exprSet[g,]) > median(as.integer(exprSet[g,])), "high", "low")
  sfit1 <- survfit(Surv(time, event) ~ gene, data = meta)
  ggsurvplot(sfit1, pval = TRUE, data = meta, risk.table = TRUE)
}) 
arrange_ggsurvplots(splots, print = TRUE,  
                    ncol = 2, nrow = 2, risk.table.height = 0.4)  # 内置拼图函数


log-rank批量生存分析

Log-Rank test:对不同组的生存率进行假设检验,是无参数检验,近似于卡方检验,零假设是组间没有差异。

由于log-rank检验需要对自变量进行分组,无法使用连续型变量,而有时候在不知道连续性变量的最佳截断值或者自变量很多的时候,只能按中位数进行分组,所以结果并没有Cox回归用连续型变量得出的结果好。所以一般先用Cox或Lasso将变量降维后,再找最佳截断值来画生存曲线。

Log-Rank检验属单因素分析方法,应用条件是除比较因素外,影响生存率的其他因素组件均衡可比,否则应矫正各因素的影响,可采用Cox比例风险回归模型。
用apply()函数批量计算所有表达矩阵中基因的生存分析p值,从而挑选出“显著基因”。这里用表达矩阵的tpm值进行计算

mySurv <- with(meta, Surv(time, event == "1"))  # 创建生存对象,event == 1表示“1为结局时间发生“
log_rank_p <- pbapply(exprSet, 1, function(gene){
  # gene <- exprSet[1,]
  meta$group <- ifelse(gene > median(gene), "high", "low") 
  data.survdiff <- survdiff(mySurv ~ group, data = meta)
    # survdiff()用于检验两条或多条生存曲线之间是否存在差异,
      # 或者针对已知替代项检验单条曲线,也适用于分组资料以及多组间生存曲线的比较;
  p.val <- 1 - pchisq(data.survdiff$chisq, length(data.survdiff$n) - 1)  # 计算log-rank检验的p值
  return(p.val)
})
log_rank_p <- sort(log_rank_p)  # 取出每一个基因生存分析的P值,形成表
table(log_rank_p < 0.01)  # 哪些是P<0.01的
table(log_rank_p < 0.05)  # 哪些是P<0.05的

log_rank <- names(log_rank_p)[log_rank_p < 0.05]  # log-rank检验筛选的差异基因

log-rank批量生存分析结果如下:

KM曲线的优势:可以直接从图中看出组间差异。
KM曲线的局限性:1.无法得知暴露因素对结局的影响是非暴露组多少倍;2.没有控制其他变量。

要解决以上局限性,需引入Cox比例风险回归模型,进行多变量Cox回归分析,得到风险差异的具体估计值HR。
Cox比例风险回归分析的优势在于可以分析分类变量与数值变量,并且将生存分析的范围由单因素拓展到多因素的分析。
Cox比例风险回归模型可以同时分析几个因素的生存。另外,统计模型提供每个因素的效果大小。

Cox比例风险回归

Cox比例风险回归模型可以分析多个因素对生存事件的影响,而且允许有删失。是生存分析中重要的多因素分析方法。
Cox回归本质上是一种回归模型,它没有直接使用生存时间,而是使用了风险比(hazard ratio)作为因变量。
该模型不用于估计生存率,而是用于因素分析,也就是找到某一个危险因素对结局事件发生的贡献度。

Cox回归的重要统计指标:风险比(hazard ratio,HR),表示变量X变化一个单位引起风险的变化。
当HR > 1时,说明研究对象是一个危险因素。
当HR < 1时,说明研究对象是一个保护因素。
当HR = 1时,说明研究对象对生存时间不起作用。

Cox批量单因素生存分析 Univariate Cox Analysis

mySurv <- with(meta, Surv(time, event == "1"))  # 创建生存对象,event = 1表示“1为结局事件发生”
unicox_results <- pbapply(exprSet, 1, function(gene){  # 对表达矩阵exprSet中的每一行(基因)执行函数function
  # gene = as.numeric(exprSet[1,]) # 举个例子
  group <- ifelse(gene > median(gene), "high","low")  # 标记不同样本中该基因的上下调,将表达量转换为二分类变量
  survival_dat <- data.frame(group = group,
                             stage = meta$stage,
                             age = meta$age,
                             gender = meta$gender,
                             gene = gene,  # 基因表达量
                             stringsAsFactors = F)  # 选择用于生存分析的数据
  # 拟合Cox比例风险回归模型 m :
  m <- coxph(mySurv ~ gender + age + stage + group, data = survival_dat)  # 表达量用二分类变量group
  # m <- coxph(mySurv ~ group, data = survival_dat)  # 表达量用二分类变量group
  # m <- coxph(mySurv ~ gene, data =  survival_dat)  # 表达量也可直接使用连续型变量gene
  # sm <- summary(m)  # 看拟合出的Cox比例风险回归模型的参数
    # n:总人数。
    # number of events:发生结局事件的人数,即死亡人数
    # coef(coefficients,回归系数):结果为正(负),表示男性(genderMALE)死亡风险高(低)于女性,或者说有较低(高)的生存概率。
    # exp(coef):也称为风险比(HR)。HR = 1: 无影响,HR < 1: 降低风险,HR > 1: 增加风险。
    # se(coef):coef的标准误
    # z:Wald检验的统计量,z = coef/se(coef),是否具有统计学意义看p值
    # Pr(>|z|):p值
    # low.95与upper.95表示HR值的95%置信度区间CI,如果95%CI跨越了1,一般就不认为该因素对生存有显著影响。
  beta <- coef(m)
  se <- sqrt(diag(vcov(m)))
  tmp <- round(cbind(coef = beta,  # 模型的偏回归系数β
                     se = se,  # 偏回归系数β的标准误
                     z = beta/se,  # Wald检验的统计量
                     p = 1 - pchisq((beta/se)^2, 1),  # p值,差异的统计学意义
                     HR = exp(beta),  # 风险值,计算公式为exp(coef)
                     HRCILL = exp(beta - qnorm(.975, 0, 1) * se),  # HR的95%置信区间低点
                     HRCIUL = exp(beta + qnorm(.975, 0, 1) * se)), 3)  # HR的95%置信区间高点
  return(tmp["grouplow",])  # 分类变量
  # return(tmp["gene",])  # 连续型变量
})
unicox_results <- as.data.frame(t(unicox_results))
table(unicox_results[,4] < 0.01)  # p值<0.01的有多少
table(unicox_results[,4] < 0.05)  # p值<0.05的有多少

unicox <- rownames(unicox_results)[unicox_results[,4] < 0.05]  # Cox单因素分析筛选的差异基因

Cox批量单因素生存分析结果如下:


 Cox多因素生存分析 Multivariable Cox Analysis

mySurv <- with(meta, Surv(time, event == "1")) # 创建生存对象
survival_dat <- as.data.frame(t(exprSet))
# 拟合Cox比例风险回归模型 m :
m <- coxph(mySurv ~ LINC02185 + AL391845.2 + LINC00858, data = survival_dat) # 表达量用连续型变量
# sm <- summary(m) # 看拟合出的Cox比例风险回归模型的参数
  # n:总人数。
  # number of events:发生结局事件的人数,即死亡人数
  # coef(coefficients,回归系数):结果为正(负),表示男性(genderMALE)死亡风险高(低)于女性,或者说有较低(高)的生存概率。
  # exp(coef):也称为风险比(HR)。HR = 1: 无影响,HR < 1: 降低风险,HR > 1: 增加风险。
  # se(coef):coef的标准误
  # z:Wald检验的统计量,z = coef/se(coef),是否具有统计学意义看p值
  # Pr(>|z|):p值
  # low.95与upper.95表示HR值的95%置信度区间CI,如果95%CI跨越了1,一般就不认为该因素对生存有显著影响。
beta <- coef(m)
se <- sqrt(diag(vcov(m)))
multicox_results <- round(cbind(coef = beta,  # 模型的偏回归系数β
                                se = se,  # 偏回归系数β的标准误
                                z = beta/se,  # Wald检验的统计量
                                p = 1 - pchisq((beta/se)^2, 1),  # p值,差异的统计学意义
                                HR = exp(beta),  # 风险值,计算公式为exp(coef)
                                HRCILL = exp(beta - qnorm(.975, 0, 1) * se),  # HR的95%置信区间低点
                                HRCIUL = exp(beta + qnorm(.975, 0, 1) * se)), 3)  # HR的95%置信区间高点
table(multicox_results[,4] < 0.01)  # p值<0.01的有多少
table(multicox_results[,4] < 0.05)  # p值<0.05的有多少

multicox <- rownames(multicox_results)[multicox_results[,4] < 0.05]  # Cox多因素分析筛选的差异基因

取交集

length(intersect(log_rank, intersect(unicox, multicox))) # 可以取交集用于后续分析,也可任选lr或cox之一进行分析。

 

 

一些文章:

TCGA系列学习笔记(6)多因素生存分析

生存分析中连续型自变量截断值的确定方法

一些生存分析相关基础概念:生存分析(Survival analysis)的总结整理

 Kaplan-Meier曲线原理详解:画说统计 | 生存分析之Kaplan-Meier曲线都告诉我们什么

log-rank检验和Wilcoxon检验的区别:log-rank检验在什么情况下失效?

用R来做KM生存分析详解:R语言-Survival analysis(生存分析)

Cox与KM生存分析及结果解读:Cox与KM生存分析及结果解读

强烈推荐——sthda官网R代码:Cox Proportional-Hazards Model

Cox回归生存分析 - 简书:Cox回归生存分析

R语言实现及结果解读:生存分析的Cox回归模型(比例风险模型)R语言实现及结果解读

【8文合集】全面了解单因素分析和多因素分析:【8文合集】全面了解单因素分析和多因素分析

posted on 2023-02-16 23:20  小高不高  阅读(2553)  评论(0编辑  收藏  举报