生存预后不显著?最佳阈值来帮你!| 附完整代码 + 注释

2024-03-14 00:28

本文主要是介绍生存预后不显著?最佳阈值来帮你!| 附完整代码 + 注释,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大家在进行生存预后分析时发现结果不显著,是不是当头一棒!两眼一黑!难不成这就代表我们的研究没意义吗?NONONO!别慌!说不定还有救!快来看看最佳阈值能不能捞你一把!

对生存分析感兴趣的小伙伴可以查看:看完不会来揍我 | 生存分析详解 | 从基础概念到生存曲线绘制 | 代码注释 + 结果解读

生存分析不显著怎么办

通常情况下,为了确定一个二分变量(例如基因表达高/低)的最佳阈值,我们可能会使用中位数作为阈值,将样本分为两组,然后对生存曲线进行比较。但有时候使用中位数作为阈值可能并不足以找到显著的差异,这时可以考虑使用最佳阈值方法来寻找更加适合的阈值。来!咱们今天就一起去xio习一下!

老规矩!本文所用到的数据和代码,我已经上传到了GitHub,有需要的话,大家可以在公众号后台回复最佳阈值即可获得存放数据的链接,很多需要注意的问题也会在代码注释中进行详细说明。不过我在分享过程中也会把每一步的输入数据和输出结果进行展示,大家可以作为参考并调整自己的数据格式,然后直接用自己的数据跑,也是没有任何问题的!

# 生存预后不显著?最佳阈值来帮你!# 加载包,没安装的记得安装一下哟!
library(survival)
library(survminer)# 加载数据
best_threshold_data <- read.csv("./best_threshold_data.csv")
head(best_threshold_data)
#            sample risk_score OS OS.time
# 1 TCGA-06-0878-01   2.538694  0     218
# 2 TCGA-26-5135-01   3.736050  1     270
# 3 TCGA-06-5859-01   3.701219  0     139
# 4 TCGA-06-2563-01   3.318001  0     932
# 5 TCGA-41-2571-01   5.102783  1      26
# 6 TCGA-28-5207-01   6.899652  1     343# 数据包含了四列:样本名称(sample)、风险评分(risk_score)、生存状态(OS)和生存时间(OS.time)。# 使用中位数作为阈值来将样本分为高风险组和低风险组
# 如果风险评分大于等于中位数,则标记为"High Risk",否则标记为"Low Risk"
best_threshold_data$group <- ifelse(best_threshold_data$risk_score >= median(best_threshold_data$risk_score), "High Risk", "Low Risk")# 创建生存对象(Surv对象),包含生存时间和生存状态信息
surv_obj <- Surv(time = best_threshold_data$OS.time, event = best_threshold_data$OS)# 使用survfit()函数拟合生存曲线
surv_fit <- survfit(surv_obj ~ best_threshold_data$group)# 绘制生存曲线
ggsurvplot(surv_fit, data = best_threshold_data, surv.median.line = "hv",pval = TRUE,  # 显示p值xlab = "Time (days)", ylab = "Survival Probability",  # x轴和y轴标签legend.title = "",  # 图例标题为空break.x.by = 1000,  # x轴刻度间隔color = "strata",  # 根据分组着色palette = c("#bc5148", "#3090a1"))  # 自定义颜色

哎!最恶毒的诅咒莫过于“祝你P > 0.05”!!!这不显著可咋整,咱这分析不就没意义了嘛!

且慢!我们的救兵来啦!下面请欣赏它的表演!

最佳阈值选择

目前比较常见的方法有:

  • 使用survminer包中的surv_cutpoint函数实现
  • 使用cutoff包中的logrank函数实现
  • 基于X-Tile软件实现

下面,咱们就挨个介绍!

survminer包的surv_cutpoint函数

# survminer包的surv_cutpoint函数
# 使用survminer包的surv_cutpoint函数来寻找最佳阈值
best_threshold_surv <- surv_cutpoint(best_threshold_data,time = "OS.time",  # 生存时间列名event = "OS",      # 生存事件列名variables = "risk_score",  # 需要寻找阈值的变量列名minprop = 0.3,     # 最小比例,防止找到的阈值过于极端progressbar = TRUE)  # 显示进度条# 查看找到的最佳阈值的摘要统计信息
summary(best_threshold_surv)
#            cutpoint statistic
# risk_score 4.420631  1.748393# 我们这里只计算了一个变量的最佳阈值,还可以计算多个变量的最佳阈值,只需将`variables`参数设为`c("变量1, "变量2", "变量3")`。# 根据找到的最佳阈值对数据进行分组
best_threshold_data <- surv_categorize(best_threshold_surv)# 创建生存对象(Surv对象),包含生存时间和生存状态信息
surv_obj <- Surv(time = best_threshold_data$OS.time, event = best_threshold_data$OS)# 使用survfit()函数拟合生存曲线
surv_fit <- survfit(surv_obj ~ best_threshold_data$risk_score)# 绘制生存曲线
ggsurvplot(surv_fit, data = best_threshold_data, surv.median.line = "hv",pval = TRUE,                    # 显示p值xlab = "Time (days)", ylab = "Survival Probability",  # x轴和y轴标签legend.title = "",             # 图例标题为空break.x.by = 1000,             # x轴刻度间隔color = "strata",              # 根据分组着色palette = c("#bc5148", "#3090a1"))  # 自定义颜色

是不是比上面显著多啦!

cutoff包的logrank函数

# cutoff包的logrank函数# 重新加载数据
best_threshold_data <- read.csv("./best_threshold_data.csv")# 加载cutoff包
library(cutoff)# 使用cutoff包的logrank函数来寻找最佳阈值
best_threshold_surv_2 <- logrank(data = best_threshold_data,time = "OS.time",  # 生存时间列名y = "OS",          # 生存事件列名x = "risk_score",  # 需要寻找阈值的变量列名cut.numb = 1,      # 截点个数n.per = 0.2,       # 分组后每组样本量占总样本量的最小比例y.per = 0.1,       # 分组后每组中较少结果的最小比例p.cut = 0.1,       # p值截断round = 5)         # 保留几位小数# 打印找到的最佳阈值及相关信息
best_threshold_surv_2[order(best_threshold_surv_2$pvalue, decreasing = F), ]
#      cut1      n           n.per     y           y.per  pvalue p.adjust
# 1 4.420631 103/51 0.66883/0.33117 76/47 0.73786/0.92157 0.07617 7.08378 # 根据找到的最佳阈值对数据进行分组
best_threshold_data$Group = ifelse(best_threshold_data$risk_score >= best_threshold_surv_2[order(best_threshold_surv_2$pvalue, decreasing = F), ][1, 1],"High Risk","Low Risk")# 创建生存对象(Surv对象),包含生存时间和生存状态信息
surv_obj <- Surv(time = best_threshold_data$OS.time, event = best_threshold_data$OS)# 使用survfit()函数拟合生存曲线
surv_fit <- survfit(surv_obj ~ best_threshold_data$Group)# 绘制生存曲线
ggsurvplot(surv_fit, data = best_threshold_data, surv.median.line = "hv",pval = TRUE,                    # 显示p值xlab = "Time (days)", ylab = "Survival Probability",  # x轴和y轴标签legend.title = "",             # 图例标题为空break.x.by = 1000,             # x轴刻度间隔color = "strata",              # 根据分组着色palette = c("#bc5148", "#3090a1"))  # 自定义颜色

虽然不如刚刚那个,但也比原来好多啦是不!

X-Tile

这个我就不详细介绍啦!有兴趣的小伙伴们可以去点点点试试!

官网:https://medicine.yale.edu/lab/rimm/research/software/

教程:https://cloud.tencent.com/developer/news/283239

小小总结

  1. survminer包的surv_cutpoint函数
    • 基于maxstat包的maxstat.test函数计算出Maximally Selected Rank Statistics,通过最大化差异来确定最佳阈值。
    • 可以同时计算多个变量的最佳截断值。
    • 一次只能找到一个最佳截断值,无法同时找到多个截断值。
  2. cutoff包的logrank函数
    • 在自由度固定的情况下,计算log-rank卡方值,通过检验分组之间的差异来确定最佳阈值。
    • 提供了不同的函数用于计算多种模型的截断点,例如cox、linear、logit等,每种模型都使用对应的统计检验来确定阈值。
    • 一次只能找到一个最佳截断值。
  3. X-tile软件
    • 基于log-rank卡方值来确定最佳截断值,将数据分为不同组,可以选择找到一个或两个最佳截断值,以将数据分成两组或三组。
    • 一次只能计算一个变量的最佳阈值。

大家自行选择哟!依据个人经验,俺更推荐survminer包的surv_cutpoint函数,它在多数情况下表现都还不戳!个人观点,仅供参考!最终解释权归小蛮要所有!

文末碎碎念

那今天的分享就到这里啦!我们下期再见哟!

最后顺便给自己推荐一下嘿嘿嘿!

如果我的分享对你有用的话,欢迎关注点赞在看转发分享阿巴阿巴阿巴阿巴巴巴!这可是我的第一原动力!

蟹蟹你们的喜欢和支持!!!

啊对!如果小伙伴们有需求的话,也可以加入我们的交流群:一定要知道 | 永久免费的生信交流群终于来啦!

还有兴趣的话,也可以看看我掏心掏肺的干货满满 | 给生信小白的入门小建议 | 掏心掏肺版!绝对干货满满!

如果有小伙伴对付费分析有需求的话,可以看看这里:个性化科研服务 | 付费分析试营业正式启动啦!定制你的专属生信分析!可提供1v1答疑!

入群链接后续可能会不定期更新,主要是因为群满换码或是其他原因,如果小伙伴点开它之后发现,咦,怎么失效啦!不要慌!咱们辛苦一下动动小手去主页的要咨询那里,点击进交流群即可入群!

参考资料
  1. https://cloud.tencent.com/developer/article/1875291
  2. https://mp.weixin.qq.com/s/pOgbzHZNQC8z7KdrrrNd1A
  3. https://mp.weixin.qq.com/s/TB43jWO7CX8_o2eUXWl1Fw

这篇关于生存预后不显著?最佳阈值来帮你!| 附完整代码 + 注释的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/806699

相关文章

Java 的ArrayList集合底层实现与最佳实践

《Java的ArrayList集合底层实现与最佳实践》本文主要介绍了Java的ArrayList集合类的核心概念、底层实现、关键成员变量、初始化机制、容量演变、扩容机制、性能分析、核心方法源码解析、... 目录1. 核心概念与底层实现1.1 ArrayList 的本质1.1.1 底层数据结构JDK 1.7

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Nginx搭建前端本地预览环境的完整步骤教学

《Nginx搭建前端本地预览环境的完整步骤教学》这篇文章主要为大家详细介绍了Nginx搭建前端本地预览环境的完整步骤教学,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录项目目录结构核心配置文件:nginx.conf脚本化操作:nginx.shnpm 脚本集成总结:对前端的意义很多

Java集合之Iterator迭代器实现代码解析

《Java集合之Iterator迭代器实现代码解析》迭代器Iterator是Java集合框架中的一个核心接口,位于java.util包下,它定义了一种标准的元素访问机制,为各种集合类型提供了一种统一的... 目录一、什么是Iterator二、Iterator的核心方法三、基本使用示例四、Iterator的工

Java 线程池+分布式实现代码

《Java线程池+分布式实现代码》在Java开发中,池通过预先创建并管理一定数量的资源,避免频繁创建和销毁资源带来的性能开销,从而提高系统效率,:本文主要介绍Java线程池+分布式实现代码,需要... 目录1. 线程池1.1 自定义线程池实现1.1.1 线程池核心1.1.2 代码示例1.2 总结流程2. J

在Ubuntu上打不开GitHub的完整解决方法

《在Ubuntu上打不开GitHub的完整解决方法》当你满心欢喜打开Ubuntu准备推送代码时,突然发现终端里的gitpush卡成狗,浏览器里的GitHub页面直接变成Whoathere!警告页面... 目录一、那些年我们遇到的"红色惊叹号"二、三大症状快速诊断症状1:浏览器直接无法访问症状2:终端操作异常

Spring Boot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)

《SpringBoot分层架构详解之从Controller到Service再到Mapper的完整流程(用户管理系统为例)》本文将以一个实际案例(用户管理系统)为例,详细解析SpringBoot中Co... 目录引言:为什么学习Spring Boot分层架构?第一部分:Spring Boot的整体架构1.1

mybatis直接执行完整sql及踩坑解决

《mybatis直接执行完整sql及踩坑解决》MyBatis可通过select标签执行动态SQL,DQL用ListLinkedHashMap接收结果,DML用int处理,注意防御SQL注入,优先使用#... 目录myBATiFBNZQs直接执行完整sql及踩坑select语句采用count、insert、u

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

nodejs打包作为公共包使用的完整流程

《nodejs打包作为公共包使用的完整流程》在Node.js项目中,打包和部署是发布应用的关键步骤,:本文主要介绍nodejs打包作为公共包使用的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言一、前置准备二、创建与编码三、一键构建四、本地“白嫖”测试(可选)五、发布公共包六、常见踩坑提醒