生存分析的R包一般用survival
包和survminer
包。survival
包用于分析,survminer
包用于绘图。
survival
包核心函数:
Surv()
:创建生存对象survfit()
:使用公式或以构建的cox模型拟合生存曲线coxph()
:拟合cox比例风险回归模型survdiff()
:用log-rank或mantel-Haenszel test 检验生存差异cox.zph()
:检验cox模型的比例风险假设data$surv <- Surv(time, status)
Surv(time, time2, event, type=c('right', 'left', 'interval', 'counting', 'interval2', 'mstate'),origin=0)
# time:对于右删失,即指随访时间。若为区间数据,则为区间数据的开始时间
# time2: 区间数据,则为区间数据的结束时间
# event: 结局变量。默认0为删失,1为出现终点事件。可以自己指定终点事件。data$status == 2表示认为值为2时终点事件发生
# type:制定删失类型。但是type在不特别指定的情况下,一般会自动根据数据进行默认选择
lung$surv <- Surv(time = lung$time, lung$status == 2)
绘制生存曲线,比较生存率
ggsurvplot()
:绘制生存曲线library("survival") # cox
library("survminer") # data visualization
head(lung)
# 拟合Kaplan-Meier曲线
sfit <- survfit(formula = Surv(time, status)~1,data = lung) #总体
summary(sfit)
sfit <- survfit(formula = Surv(time, status)~sex, data = lung) # 分组
summary(sfit)
summary(sfit, times=seq(0, 1000, 100)) # 设定时间参数来选定时间区间
ggsurvplot(sfit, data = lung)
res.sum <- surv_summary(sfit)
head(res.sum[res.sum$sex==1,])
head(res.sum[res.sum$sex==2,])
ggsurvplot(sfit,pval = TRUE, conf.int = TRUE,
risk.table = TRUE) #可视化K-M生存曲线
surv_diff <- survdiff(Surv(time, status) ~ sex, data = lung) # log-rank test
surv_diff
p.val = 1 - pchisq(surv_diff$chisq, length(surv_diff$n) - 1)
p.val
lung$age_cut <- cut(lung$age, breaks = c(0, 70, Inf), labels = c("young", "old"))
fit <- survfit(Surv(time, status)~age_cut, data = lung)
## 直接用survfit()的话,它会把所有的年龄当作一个factor
summary(fit)
ggsurvplot(fit, data = lung)
surv_cutpoint()
与surv_categorize()
Cox回归分析
coxph(Surv(time, status) ~ x1 + x2 + ..., data = )
lapply(), sapply(), function()
等批量分析和展示结果ggforest()
以森林图展示各因素的HRfit <- coxph(Surv(time, status)~sex, data=lung) #univariable
summary(fit)
cox.zph(fit)
plot(cox.zph(fit))
#可视化每一个变量在cox模型下的表现。当数据出现明显分离时,则说明表现不是很理想
# univariable
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)})
hr_results <- 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 <-round(x$coef[2], 2) # exp(beta)
HR.confint.lower <- round(x$conf.int[,"lower .95"], 2)
HR.confint.upper <- round(x$conf.int[,"upper .95"],2)
HR.with.CI <- paste0(HR, " (", HR.confint.lower, "-", HR.confint.upper, ")")
res<-c(beta, HR.with.CI, wald.test, p.value)
#names(res)<-c("beta", "HR (95% CI for HR)", "wald.test", "p.value")
return(res)}
univ_results <- lapply(univ_models,hr_results)
res <- t(as.data.frame(univ_results, check.names = FALSE)) # 转置
res1 <- as.data.frame(res)
# multi-vars
res.cox <- coxph(Surv(time, status) ~ age + sex + ph.ecog, data = lung)
summary(res.cox)
ggforest(res.cox, data = lung,
main = "Hazard ratio",
cpositions = c(0.10, 0.22, 0.4),
fontsize = 1.0)
cox.zph(fit)
检验多重插补法
sum(!complete.cases(lung))
md.pattern(lung, 5)
lung_cmplt <- mice(lung, 5) # 5种可选插补
lung_cmplt_3 <- complete(lung_cmplt, 3) # 选取其中一个完整的子集进行后续分析?
lung_cmplt_3$surv <- Surv(lung_cmplt_3$time, lung_cmplt_3$status == 2)
fit <- survfit(surv~age, data = lung_cmplt)
ggsurvplot(fit, pval = TRUE)
ggsurvplot()
is a generic function to plot survival curves.ggsurvplot_list()
绘制多个对象ggsurvplot_facet()
分面到多个panelsggsurvplot_group_by()
一幅图中多个分组ggsurvplot_add_all()
总合所有的情况ggsurvplot_combine()
一个图中结合多个survfit对象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,
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))
fun="event"
,表示cumulative event 累计事件发生率fun="cumhaz"
,表示cummulative hazard累计风险水平(在时刻t,事件发生的可能性)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")
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))
ggsurvplot()
和ggforest()
的使用还需实战提高,可以使用R出矢量图后在AI中调试各种图例参数和图形的比例等。