原创 华哥生信 2026年4月12日 22:31
CNS | 参考文献
scSurv 算法介绍
scSurv是一种面向单细胞层面的生存分析方法,其核心目标是解决“细胞异质性如何影响患者预后”的问题。该方法以单细胞RNA测序数据作为参考,通过深度生成模型学习细胞的潜在表达状态,并利用这些信息对具有临床随访数据的bulk RNA-seq样本进行单细胞级别的去卷积,从而推断每个样本中不同细胞状态的组成比例。在此基础上,scSurv将这些“细胞比例”作为协变量,引入扩展的Cox比例风险模型,进一步计算每一类细胞(甚至每一个细胞状态)对患者生存风险的贡献大小。与传统方法只能在“细胞类型”或“整体表达水平”上进行分析不同,scSurv实现了从“样本层→细胞层”的跨越,使研究者可以在单细胞分辨率下直接量化不同细胞对预后的正负影响,并进一步挖掘对应的关键基因和功能通路,为理解疾病机制提供更加精细和可解释的分析框架。
' fill='%23FFFFFF'%3E%3Crect x='249' y='126' width='1' height='1'%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
能解决的科学问题
scSurv主要解决的是“哪些细胞真正决定患者预后”这一核心问题,并进一步细化为多个层面:不仅可以识别哪些细胞类型与生存相关,还能够在同一细胞类型内部区分不同功能状态对预后的差异影响,从而揭示细胞异质性的真实生物学意义。同时,该方法还能挖掘与这些风险贡献相关的关键基因和通路,帮助理解其背后的分子机制;结合空间转录组数据,还可以进一步定位高风险细胞在组织中的分布位置,解析“危险细胞”在肿瘤微环境中的空间组织方式。整体来看,scSurv把传统“相关性分析”提升为“细胞—状态—空间—预后”的系统性解析框架,使我们能够从单细胞层面系统理解疾病进展与临床结局之间的联系。
生信分析启发
scSurv带来的最大启发是:在生信分析中,不应只停留在“分群+注释+差异分析”这一传统流程,而应进一步思考这些细胞是否真正与临床结局相关,以及它们的作用是正向还是负向。具体来说,一方面需要从“细胞类型”走向“细胞状态”,避免过度依赖聚类标签带来的信息损失;另一方面要主动将单细胞数据与临床数据(如生存、疗效)进行整合,而不是各自独立分析。
代码实操#
1、创建conda环境并激活
conda create -n scSurv python=3.12conda activate scSurv
2、安装scSurv包
pip install scsurv
3、下载表达矩阵
作者提供的示例数据是 GEO 数据库中的黑色素瘤单细胞表达矩阵文件 GSE115978_counts.csv.gz 。这个文件里存的是基因表达计数,是后面构建单细胞对象的核心数据。
!wget https://ftp.ncbi.nlm.nih.gov/geo/series/GSE115nnn/GSE115978/suppl/GSE115978_counts.csv.gz
4、下载注释文件
下载该数据集对应的细胞注释文件 GSE115978_cell.annotations.csv.gz 。这个文件通常包含每个细胞的类别、样本来源等信息,后面会作为 obs 元数据写入 AnnData 对象中。
!wget https://ftp.ncbi.nlm.nih.gov/geo/series/GSE115nnn/GSE115978/suppl/GSE115978_cell.annotations.csv.gz
5、导入包
import pandas as pdimport scanpy as scfrom scipy.sparse import csr_matriximport scsurv.workflow as workflowimport matplotlib.pyplot as pltimport os
6、读取数据
## 这一段代码是从 scsurv 包自带的数据目录中读取教程需要的配套文件。from importlib.resources import files, as_filebase = files("scsurv") / "data"ref_genes = (base / "SKCM_ref_5000genes.txt").read_text(encoding="utf-8").splitlines()with as_file(base / "SKCM_checkpoint.pt") as p: saved_pt = str(p)with as_file(base / "SKCM_umap_coordinates.csv") as p: umap_df = pd.read_csv(p, index_col=0)
SKCM_ref_5000genes.txt:读取黑色素瘤教程预先筛好的 5000 个参考基因SKCM_checkpoint.pt:读取已经训练好的 scSurv 模型参数文件SKCM_umap_coordinates.csv:读取已经准备好的 UMAP 坐标,后面直接用于可视化
7、构建单细胞对象 s c_adat a
把原始下载的数据整理成 scSurv 可以直接使用的标准单细胞输入对象
# 读取表达矩阵 counts,并转置,让“行=细胞,列=基因”count_df = pd.read_csv('GSE115978_counts.csv.gz', index_col=0).T
# 读取细胞注释表 annotationannotation_df = pd.read_csv('GSE115978_cell.annotations.csv.gz', index_col=0)# 用表达矩阵和注释信息创建 AnnData 对象sc_adata = sc.AnnData(X=csr_matrix(count_df.values), obs=annotation_df)# 设置基因名sc_adata.var_names = count_df.columns# 把细胞注释信息写入 obssc_adata.obs = annotation_df# 把不明确的细胞类型统一处理sc_adata.obs['cell.types'] = sc_adata.obs['cell.types'].replace('?', 'Undifined')# 把官方给好的 UMAP 坐标写入 obsm['X_umap']sc_adata.obsm['X_umap'] = umap_df<a href="'UMAP1'%2C'UMAP2'">'UMAP1','UMAP2'</a>.to_numpy()# 最后只保留参考基因列表 ref_genes 中的基因sc_adata = sc_adata[:, ref_genes].copy()
8、设置运行参数
8.1这里没有手动传入 bulk 的 AnnData 对象,因为教程会依赖预训练资源或内置流程
bulk_adata = None
8.2 指定单细胞数据里表示批次/样本来源的列名是
batch_key = 'samples'
8.3 没有额外指定实验名称
exp_name = None
8.4 设定训练轮数上限为 10000
epoch = 10000
9、运行 scSurv
这里传了 saved_path=saved_pt ,所以这一步是在 加载官方训练好的模型参数并执行 scSurv 流程 ,而不是从头开始完整训练。
sc_adata, bulk_adata, _, _, scsurv_exp = workflow.run_scSurv( sc_adata, bulk_adata, exp_name, epoch, batch_key, saved_path=saved_pt)
- 输入:
sc_adata、batch_key、训练轮数、预训练 checkpoint - 输出:更新后的
sc_adata、bulk_adata、以及scsurv_exp这个实验结果对象
10、运行结果做后处理
这一步会把模型输出整理回 AnnData 对象里,比如把低维表示、去卷积结果、风险贡献值等附加到 sc_adata 或 bulk_adata 中,方便后面直接画图和解释结果。
sc_adata, bulk_adata, _ = workflow.post_process(scsurv_exp, sc_adata, bulk_adata)
11、可视化
os.makedirs('fig', exist_ok=True)fig, ax = plt.subplots(figsize=(8, 6))sc.pl.umap(sc_adata, color='cell.types', ax=ax, show=False, colorbar_loc=None, frameon=False, legend_fontsize=11)ax.set_title('', fontsize=20)plt.savefig('fig/SKCM_umap_celltype.png', bbox_inches='tight')
' fill='%23FFFFFF'%3E%3Crect x='249' y='126' width='1' height='1'%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
不同细胞类型在UMAP空间中清晰分离,为后续分析“哪些细胞影响生存”提供基础。
fig, ax = plt.subplots(figsize=(9, 6))sc.pl.umap(sc_adata, color='beta_z', ax=ax, show=False, colorbar_loc='right', frameon=False)ax.set_title('Contribution to hazard', fontsize=20)plt.savefig('fig/SKCM_umap_beta_z.png')
' fill='%23FFFFFF'%3E%3Crect x='249' y='126' width='1' height='1'%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
scSurv将生存信息映射到单细胞层面,揭示不同细胞(甚至同一细胞类型内部)对预后的差异性贡献。这一步真正把“谁在影响生存”从样本层面下沉到了单细胞层面。
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(18, 6))sc.pl.umap(sc_adata, color='SPP1', ax=ax1, show=False, colorbar_loc='right', layer='xld', frameon=False, color_map='magma')ax1.set_title('SPP1 expression', fontsize=20)sc.pl.umap(sc_adata, color='TNFSF10', ax=ax2, show=False, colorbar_loc='right', layer='xld', frameon=False, color_map='magma')ax2.set_title('TNFSF10 expression', fontsize=20)plt.savefig('fig/SKCM_umap_SPP1_TNFSF10.png')
' fill='%23FFFFFF'%3E%3Crect x='249' y='126' width='1' height='1'%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E)
SPP1与差预后相关,而TNFSF10与好预后相关,验证了scSurv识别的风险细胞具有明确的分子基础。这一步把“风险细胞”进一步落实到具体基因,完成了从细胞到分子机制的闭环解释。
欢迎加入CNS生信交流群一起讨论与研究时下热门CNS文章各类生信分析方法(若二维码过期可以添加微信:huagesx)
孟德尔+单细胞全文复现
零基础想学生信,看 👇 这个文章 :
想学机器学习,看 👇 这个文章 :
AI助力多组学与机器学习联合分析(机器学习分析代谢组、蛋白组、宏基因组、网络药理学、转录组)
想系统学单细胞,看 👇 这个文章 :
CNS文章单细胞数据分析内容汇总(基础--进阶--python分析)
想系统学空间转录组,看 👇 这个文章 :
跟着CNS文章学空间转录组分析线上直播课(Visium HD、Xenium、Stereo-seq)
欢迎关注 | 华哥科研平台
亲,写的这么辛苦,记得关注、点赞、转发哟!
继续滑动看下一个
Bioinformation
向上滑动看下一个
闪记
复制 LaTeX 公式