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¶
| 特性 | PCA | CCA | MOFA+ |
|---|---|---|---|
| 输入数据 | 单一矩阵 | 两个矩阵 | 任意多个矩阵 |
| 多组学 | 不支持 | 两种 | 不限 |
| 多样本 | 不支持 | 不支持 | 支持(Group) |
| 缺失值 | 不支持 | 不支持 | 自动处理 |
| 稀疏性 | 不支持 | 不支持 | 支持(ARD先验) |
二、MOFA+分析流程¶
2.1 安装¶
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先验会自动"关掉"不重要的因子