cbioportal.org/study/summary?id=msk_impact_2017
library(survival)library(survminer)library(randomForestSRC)library(timeROC)library(data.table)library(tidyr)library(dplyr)library(tibble)library(caret)
## 临床数据清洗clin <- fread('data_clinical_patient.txt',data.table = F,skip = 4)ID <- fread('data_clinical_sample.txt',data.table = F,skip = 4)ID <- ID[,c(1,2,10)] ##选取ID信息和转移信息clin <- merge(ID,clin,by=1)clin <- clin[,c(2,3,5,7)]%>%na.omit()clin$VITAL_STATUS <- ifelse(clin$VITAL_STATUS=='ALIVE',0,1)clin$OS_MONTHS <- clin$OS_MONTHS/12 ##转化为年为单位的时间colnames(clin) <- c('ID','PM','OS','OS.time')clin <- clin[clin$OS.time!=0,] ##删除生存时间为0的样本length(unique(clin$ID)) ## 查看有无重复样本
我们最后一共得到了8130个符合要求的样本
##Mutation signature 数据清洗ms <- fread('data_mutational_signature_contribution.txt',data.table = F)[,-c(1,3:5)]ms <- ms%>%column_to_rownames('NAME')%>%t()%>%as.data.frame()head(ms[,1:5])
# merge clinical data and Mutation signature # divide all data into trian and validation datadata <- merge(clin,ms,by.x=1,by.y = 0)head(data[,1:8])set.seed(2020911)size <- createDataPartition(data$OS,p=0.7,list = F) # 随机选择70%的数据作为Train datatrain <- data[size,]validation <- data[-size,]
具有完整临床信息和 Mutation signature 信息的样本一共7268个,以 7:3 的比例分为训练集和验证集。
##构建随机生存森林rsf_t <- rfsrc(Surv(OS.time,OS)~.,data = train[,-c(1:2)],ntree = 1000,nodesize = 15,##该值建议多调整splitrule = 'logrank',importance = T,proximity = T,forest = T,seed = 2020911)rsf_t
plot(rsf_t)
左图描述了 oob error rate 随着数的数量变化的趋势,可以看到,当 ntree > 200 左右的时候,oob error rate 趋于稳定。 右图则描述了 30 个 signature 的重要性,可以看出 signature 28 的重要性最强
## 获得每个样本的 riskscore,进一步进行下游分析score_t <- data.frame(train[,c(1,3,4)],Score=rsf_t$predicted)cut <- surv_cutpoint(score_t,'OS.time','OS','Score')cut
plot(cut)
Optimal Cutpoint = 252.56
## 生存分析cat <- surv_categorize(cut)fit <- survfit(Surv(OS.time,OS)~Score,cat)mytheme <- theme_survminer(font.legend = c(14,"plain", "black"),= c(14,"plain", "black"),= c(14,"plain", "black")) ## 自定义主题
ggsurvplot(fit,cat,palette = 'jco',size=1.3,pval=T,legend.labs=c("High","Low"),legend.title='Score',xlab="Time(years)",ylab='Overall survival',ggtheme = mytheme)
# ROCcol <- c("#0073C2FF","firebrick1","orange") ## 自定义颜色tt <- timeROC(score_t$OS.time,score_t$OS,score_t$Score, cause = 1,weighting = 'marginal', times = seq(0.5,3,0.5),ROC = T,iid = T)AUC
plotAUCcurve(tt,conf.int = T,col = "tomato")
plot(tt,time=1,title=FALSE,lwd=1.5,col=col[1])plot(tt,time=2,col=col[2],add=TRUE,title=FALSE,lwd=1.5)plot(tt,time=3,col=col[3],add=TRUE,title=FALSE,lwd=1.5)id <- c(paste0("1-Year AUC = ",round(tt$AUC[2],3)), paste0("2-Year AUC = ",round(tt$AUC[4],3)), paste0("3-Year AUC = ",round(tt$AUC[6],3)))legend("bottomright",id, fill=col[1:3], bty="o",cex=1, border = NA)abline(0,1,lty=2,lwd=0.5)
KM分析显示了 High risk 与不良的预后有着显著的关系; ROC则显示了该模型在训练集中的准确性较高。
# 训练集rsf_v<- predict(rsf_t,newdata = validation,proximity=T)score_v <- data.frame(validation[,c(1,3,4)],Score=score_v$predicted)Group <- ifelse(score_v$Score>cut$cutpoint$cutpoint,'High','Low')
fit <- survfit(Surv(OS.time,OS)~Group,score_v)ggsurvplot(fit,palette = 'jco',size=1.3,pval=T,legend.labs=c("High","Low"),legend.title='Score',xlab="Time(years)",ylab='Overall survival',ggtheme = mytheme)
vv <- timeROC(score_v$OS.time,score_v$OS,score_v$Score, cause = 1,weighting = 'marginal', times = seq(0.5,3,0.5),ROC = T,iid = T)vv$AUC
可以看出,尽管KM也很显著,但是ROC则表明了该模型在训练集中的准确度很低。 在该文的第3-4张插图中,也表明错误率很高:44.8%。这其实已经说明了模型的泛化能力很弱。 我们可以通过调整参数,比如 ntree,nodesize,nsplit,mtry 等参数来优化模型,不过由于错误率太高,我估计优化后效果也不会很好。所以,该数据可能不太适合用随机生存森林来处理。
Summary:
使用随机生存森林的思路大致就是这样,当然也可以通过 rf 筛选重要变量后使用其它算法进行建模,方式很多样,重在尝试,以结果为导向,总有一个Model是让你满意的。 对于外部验证队列,可以直接使用TCGA和ICGC中提供的信息。 另外,临床信息中还有远处转移信息,可以基于转移信息和30个MS 构建模型,而且,MSK中不止有 MS 信息,还有 CNA,mutation,SV 等信息,都可以进行尝试下。
微信扫一扫
关注该公众号