跳转至

单细胞肿瘤异质性分析


一句话说明

肿瘤不是一团均匀的坏细胞,而是由多个遗传背景不同的"亚群"组成的混合体,单细胞测序能看清每个细胞的突变和表达差异,揭示肿瘤内部的异质性格局。


核心知识点

1. 肿瘤异质性层次

  • 瘤间异质性(inter-tumor):不同患者的肿瘤不同(白话:每个病人的肿瘤都独一无二)
  • 瘤内异质性(intra-tumor):同一个肿瘤内不同区域/细胞不同(白话:一个肿瘤内部也不统一)
  • 时间异质性:治疗前后肿瘤的组成变化
  • 白话类比:肿瘤像一个生态系统,里面住着不同"物种"(亚克隆),它们竞争、合作、演化

2. 单细胞分析揭示的异质性维度

维度方法工具
转录异质性scRNA-seq 聚类Seurat, Scanpy
基因组异质性单细胞CNV推断InferCNV, CopyKAT
克隆结构突变追踪Clonealign, Cardelino
细胞状态轨迹分析Monocle3, scVelo
微环境互作通讯分析CellChat, CellPhoneDB

3. InferCNV 从表达推断 CNV

  • 原理:如果某个染色体区域的基因表达整体偏高/偏低,可能是因为拷贝数变了
  • 需要正常细胞作为参考(从同一数据中选择免疫细胞或成纤维细胞)
  • 可以区分不同 CNV 模式的亚克隆

4. 肿瘤微环境(TME)解析

  • 免疫细胞:T 细胞(CD8+ 效应/耗竭)、Treg、巨噬细胞(M1/M2)
  • 基质细胞:成纤维细胞(CAF)、内皮细胞
  • 肿瘤细胞本身的亚群和状态

实战代码

# === 单细胞肿瘤异质性分析(Scanpy + InferCNV) ===
import scanpy as sc                    # 单细胞分析
import numpy as np                     # 数值计算

# 1. 加载和预处理
adata = sc.read_10x_h5("filtered_feature_bc_matrix.h5")  # 10X数据
adata.var_names_make_unique()          # 基因名去重

sc.pp.filter_cells(adata, min_genes=200)    # 过滤低质量细胞
sc.pp.filter_genes(adata, min_cells=3)      # 过滤低表达基因

# 计算线粒体基因比例(肿瘤细胞可能偏高)
adata.var["mt"] = adata.var_names.str.startswith("MT-")
sc.pp.calculate_qc_metrics(adata, qc_vars=["mt"], inplace=True)
adata = adata[adata.obs.pct_counts_mt < 20].copy()  # 过滤高线粒体

# 标准处理
sc.pp.normalize_total(adata, target_sum=1e4)  # 归一化
sc.pp.log1p(adata)                     # 对数变换
sc.pp.highly_variable_genes(adata, n_top_genes=3000)  # 高变异基因
sc.pp.scale(adata, max_value=10)       # 标准化
sc.tl.pca(adata, svd_solver="arpack")  # PCA降维
sc.pp.neighbors(adata, n_pcs=30)       # 构建KNN图
sc.tl.umap(adata)                      # UMAP降维
sc.tl.leiden(adata, resolution=0.8)    # Leiden聚类

# 2. 区分肿瘤细胞和非肿瘤细胞(用marker基因)
# 免疫细胞 marker
immune_markers = ["PTPRC", "CD3D", "CD8A", "CD4", "CD14", "CD68"]
# 上皮/肿瘤 marker
tumor_markers = ["EPCAM", "KRT18", "KRT19", "MUC1"]

sc.pl.dotplot(adata, immune_markers + tumor_markers,
              groupby="leiden")        # 点图查看marker表达

# 3. 手动注释细胞类型(根据marker表达)
cell_type_map = {
    "0": "Tumor", "1": "Tumor", "2": "T_cell",
    "3": "Macrophage", "4": "Tumor", "5": "Fibroblast",
    "6": "B_cell", "7": "Endothelial"  # 根据实际marker调整
}
adata.obs["cell_type"] = adata.obs["leiden"].map(cell_type_map)

# 4. 分析肿瘤细胞亚群
tumor_cells = adata[adata.obs["cell_type"] == "Tumor"].copy()
sc.tl.leiden(tumor_cells, resolution=0.5, key_added="tumor_subclone")
sc.pl.umap(tumor_cells, color="tumor_subclone",
           title="肿瘤细胞亚克隆")     # 可视化亚克隆
# === InferCNV 从 scRNA-seq 推断 CNV ===

# 1. 准备输入文件
# annotations.txt: 每个细胞的类型注释(肿瘤/正常)
# gene_order.txt: 基因在染色体上的位置

# 2. 运行 InferCNV(R 脚本)
cat > run_infercnv.R << 'RSCRIPT'
library(infercnv)                      # 加载InferCNV

# 创建 InferCNV 对象
infercnv_obj <- CreateInfercnvObject(
  raw_counts_matrix = "raw_counts.txt",    # 原始计数矩阵
  annotations_file = "annotations.txt",     # 细胞注释
  gene_order_file = "gene_order.txt",       # 基因位置
  ref_group_names = c("T_cell", "Macrophage")  # 正常参考细胞
)

# 运行分析
infercnv_obj <- infercnv::run(
  infercnv_obj,                        # InferCNV对象
  cutoff = 0.1,                        # 基因表达下限
  out_dir = "infercnv_output/",        # 输出目录
  cluster_by_groups = TRUE,            # 按组聚类
  denoise = TRUE,                      # 降噪
  HMM = TRUE,                         # 用HMM识别CNV状态
  num_threads = 8                      # 线程数
)
RSCRIPT

Rscript run_infercnv.R                 # 执行R脚本

面试常问点

★ 为什么要用单细胞测序分析肿瘤异质性?

参考答案:Bulk 测序看到的是所有细胞的平均信号,如果肿瘤中 30% 的细胞有 A 突变、另外 30% 有 B 突变,bulk 测序只能看到两个低频突变,无法知道它们是否在同一个细胞中。单细胞测序能看到每个细胞的独立状态,可以:(1) 识别不同的亚克隆及其比例;(2) 追踪克隆演化路径;(3) 发现治疗耐药的亚群(可能在治疗前就存在的少数耐药细胞);(4) 解析肿瘤微环境中免疫细胞的状态(如 T 细胞耗竭)。

★ InferCNV 推断的 CNV 准确吗?

参考答案:InferCNV 从表达量推断 CNV,是间接方法,不如 WGS 直接检测准确。它的优势是不需要额外的 DNA 测序,可以在细胞水平看 CNV 模式。大尺度的 CNV(染色体臂级别)检测比较可靠,小尺度的不太准确。最好配合 bulk WGS/WES 的 CNV 数据做验证。CopyKAT 是另一个类似的工具,用贝叶斯方法,某些情况下表现更好。


速查卡片

问题答案
瘤内异质性同一肿瘤内不同细胞/区域不同
单细胞CNV推断InferCNV, CopyKAT
转录异质性分析Seurat, Scanpy
克隆追踪突变+CNV综合判断
正常参考细胞免疫细胞、成纤维细胞
TME 解析CellChat, CellPhoneDB
亚克隆意义耐药机制、转移能力差异
T细胞耗竭标志PDCD1, CTLA4, LAG3, HAVCR2
CAF 标志FAP, ACTA2, PDGFRA
分析起点先区分肿瘤细胞和非肿瘤细胞