跳转至

751. 多组学单细胞因子分析MOFA+

一句话概述:MOFA+同时分析单细胞的多种组学数据(RNA+ATAC+蛋白+甲基化),找出驱动细胞异质性的共享因子——就像找出同时影响"成绩、体育、社交"的潜在因素,发现"她之所以各方面都好,是因为有'自律'这个底层因子"。


核心知识点速查表

概念白话解释关键工具
MOFA+多组学因子分析,扩展到单细胞Python/R
因子(Factor)驱动数据变异的潜在维度类似PCA的PC
视图(View)每种组学数据类型RNA, ATAC等
组(Group)不同样本或条件批次/条件
方差解释每个因子解释了多少变异R²值
权重(Weight)每个特征对因子的贡献类似loadings

一、原理(白话版)

1.1 为什么需要MOFA+?

当你有多种组学数据时: - scRNA-seq告诉你基因表达 - scATAC-seq告诉你染色质开放性 - CITE-seq告诉你表面蛋白 - scBS-seq告诉你DNA甲基化

问题是:如何整合这些信息?

MOFA+的思路:

假设存在一些"潜在因子"同时驱动多种组学的变异

Factor 1 可能代表"细胞分化状态"
  → 同时影响分化基因的表达(RNA)
  → 同时影响分化增强子的开放(ATAC)
  → 同时影响分化标记蛋白的表达(蛋白)

Factor 2 可能代表"细胞周期"
  → 同时影响周期基因表达(RNA)
  → 同时影响复制起点的开放(ATAC)

1.2 MOFA+ vs PCA/CCA

特性PCACCAMOFA+
输入数据单一矩阵两个矩阵任意多个矩阵
多组学不支持两种不限
多样本不支持不支持支持(Group)
缺失值不支持不支持自动处理
稀疏性不支持不支持支持(ARD先验)

二、MOFA+分析流程

2.1 安装

# Python安装
pip install mofapy2  # 安装MOFA+

# R安装
# BiocManager::install("MOFA2")

2.2 Python流程

# ===== MOFA+完整分析流程 =====
from mofapy2.run.entry_point import entry_point  # 导入入口
import pandas as pd
import numpy as np
import scanpy as sc
import matplotlib.pyplot as plt

# ===== 第一步:准备多组学数据 =====
# 假设我们有RNA和ATAC两种数据

# RNA数据
adata_rna = sc.read_h5ad("scRNA.h5ad")
sc.pp.normalize_total(adata_rna, target_sum=1e4)
sc.pp.log1p(adata_rna)
sc.pp.highly_variable_genes(adata_rna, n_top_genes=3000)
rna_matrix = adata_rna[:, adata_rna.var.highly_variable].X.toarray()

# ATAC数据(peaks × cells)
adata_atac = sc.read_h5ad("scATAC.h5ad")
sc.pp.normalize_total(adata_atac, target_sum=1e4)
sc.pp.log1p(adata_atac)
sc.pp.highly_variable_genes(adata_atac, n_top_genes=5000)
atac_matrix = adata_atac[:, adata_atac.var.highly_variable].X.toarray()

# 确保细胞匹配
common_cells = adata_rna.obs_names.intersection(adata_atac.obs_names)
rna_matched = rna_matrix[adata_rna.obs_names.isin(common_cells)]
atac_matched = atac_matrix[adata_atac.obs_names.isin(common_cells)]

# ===== 第二步:创建MOFA+对象 =====
ent = entry_point()  # 创建入口点

# 设置数据
ent.set_data_options(
    scale_groups=False,  # 不跨组缩放
    scale_views=False    # 不跨视图缩放
)

# 添加数据
# MOFA+需要的格式:list of matrices
# 每个视图(view)一个矩阵,每个组(group)一个
data = [[rna_matched],   # 视图1: RNA
        [atac_matched]]   # 视图2: ATAC

ent.set_data_matrix(
    data,
    views_names=["RNA", "ATAC"],   # 视图名称
    groups_names=["all_samples"],   # 组名称
    samples_names=[common_cells.tolist()],  # 样本名
    features_names=[
        adata_rna.var_names[adata_rna.var.highly_variable].tolist(),  # RNA特征名
        adata_atac.var_names[adata_atac.var.highly_variable].tolist()  # ATAC特征名
    ]
)

# ===== 第三步:设置模型参数 =====
ent.set_model_options(
    factors=15,          # 因子数量
    spikeslab_weights=True,  # 使用spike-and-slab先验(促进稀疏性)
    ard_weights=True     # 自动相关性检测(自动去除不重要的因子)
)

ent.set_training_options(
    iter=1000,           # 最大迭代次数
    convergence_mode="fast",  # 收敛模式
    seed=42,             # 随机种子
    gpu_mode=False       # 是否使用GPU
)

# ===== 第四步:训练模型 =====
ent.build()  # 构建模型
ent.run()    # 训练

# 保存模型
ent.save("mofa_model.hdf5")  # 保存为HDF5文件

2.3 R语言分析结果

# ===== R语言分析MOFA+结果(可视化更方便)=====
library(MOFA2)
library(ggplot2)

# 加载训练好的模型
model <- load_model("mofa_model.hdf5")

# 查看模型基本信息
print(model)
# Number of views: 2 (RNA, ATAC)
# Number of groups: 1
# Number of factors: 15
# Number of features: RNA=3000, ATAC=5000

# ===== 1. 方差分解图 =====
# 每个因子在每种组学中解释了多少变异
plot_variance_explained(model, max_r2=15)
# 关键信息:
# Factor 1 在RNA中解释10%变异,在ATAC中解释8% → 共享因子
# Factor 3 只在RNA中解释5% → RNA特异因子
# Factor 5 只在ATAC中解释3% → ATAC特异因子

# ===== 2. 因子相关性 =====
plot_factor_cor(model)
# 因子之间应该不太相关(MOFA+保证正交性)

# ===== 3. 因子可视化(类似UMAP)=====
# 用因子作为坐标
plot_factors(
  model,
  factors = c(1, 2),  # 用前两个因子
  color_by = "cell_type",  # 按细胞类型着色
  dot_size = 1
)

# ===== 4. 权重分析(哪些特征驱动哪个因子)=====
# 查看Factor 1的RNA权重(贡献最大的基因)
plot_weights(
  model,
  view = "RNA",
  factor = 1,
  nfeatures = 20,  # Top 20特征
  scale = TRUE
)

# 查看Factor 1的ATAC权重(贡献最大的peaks)
plot_weights(
  model,
  view = "ATAC",
  factor = 1,
  nfeatures = 20
)

# ===== 5. 特征热图 =====
plot_data_heatmap(
  model,
  view = "RNA",
  factor = 1,
  features = 50,  # Top 50特征
  cluster_rows = TRUE,
  cluster_cols = FALSE,
  show_colnames = FALSE
)

# ===== 6. 因子的GO富集分析 =====
library(clusterProfiler)
library(org.Hs.eg.db)

# 提取Factor 1的top基因
weights <- get_weights(model, views="RNA", factors=1, as.data.frame=TRUE)
top_genes <- weights %>% 
  arrange(desc(abs(value))) %>% 
  head(200) %>% 
  pull(feature)

# GO富集
ego <- enrichGO(
  gene = top_genes,
  OrgDb = org.Hs.eg.db,
  keyType = "SYMBOL",
  ont = "BP",
  pAdjustMethod = "BH",
  pvalueCutoff = 0.05
)
dotplot(ego, showCategory=15)

三、常见报错与解决

报错信息原因解决方案
mofapy2: convergence warning模型未收敛增加iter或减少因子数
NaN in data输入数据有NaN填补或删除NaN值
Too many factors因子数大于有效维度减少因子数(通常10-20)
HDF5 read error文件损坏重新训练并保存
View dimension mismatch各视图细胞数不一致取交集细胞
All factors near zero数据太稀疏预过滤低变异特征

四、面试高频问题

Q1: MOFA+的因子(Factor)是什么意思?

A: 因子是数据中潜在的变异来源。每个因子代表一个驱动多种组学同时变化的生物学过程。例如Factor 1可能代表"细胞分化轴",它同时影响分化基因的RNA表达和分化增强子的ATAC开放性。

Q2: 如何判断因子代表什么生物学过程?

A: ①看因子的权重(weights):哪些基因/peaks贡献最大;②对权重做GO/KEGG富集分析;③用已知的细胞标记或分组来着色因子散点图;④结合文献解释。

Q3: MOFA+和简单地连接(concatenate)多组学数据有什么区别?

A: 简单连接会让特征数量多的组学主导结果。MOFA+的优势:①每种组学独立建模;②自动学习每种组学的贡献权重;③能处理缺失值;④输出的因子有清晰的方差分解。


五、速查表

# ===== MOFA+速查 =====

# Python安装/训练
pip install mofapy2
ent = entry_point()
ent.set_data_matrix(data, views_names=["RNA","ATAC"])
ent.set_model_options(factors=15)
ent.build(); ent.run()
ent.save("model.hdf5")

# R分析结果
library(MOFA2)
model <- load_model("model.hdf5")
plot_variance_explained(model)       # 方差分解
plot_factors(model, factors=c(1,2))  # 因子散点
plot_weights(model, view="RNA", factor=1)  # 权重

# 核心概念:
# View = 组学类型(RNA, ATAC, 蛋白...)
# Group = 样本/条件
# Factor = 潜在变异来源
# Weight = 特征对因子的贡献

# 因子数选择:
# 通常10-20个,看方差解释图
# ARD先验会自动"关掉"不重要的因子