2026-07-24 经得起考验的蛋白质组定量标准分析流程

条条都是精华,顺序不要变了,就这样
用omicverse
omicverse 官方 best-practice 教程(基于 PXD000022 数据集)和 PXD000279 有 ground truth 的基准教程 ,标准顺序是这样的

1. 载入数据
   adata = ov.datasets.protein_pxd000022()

2. QC 过滤 —— 先丢掉观测太少的蛋白
   ov.protein.qc_filter(adata, min_peptides=2, min_valid=0.5)

3. 缺失机制诊断 —— 在动数据之前先看缺失性质
   ov.protein.missing_pattern(adata)
   mcar_mask, threshold = ov.protein.model_selector(adata)

4. 归一化 —— median 对齐 + log2
   ov.protein.normalize(adata, method='median', log2=True)

5. 插补 —— 按机制选算法(MNAR → qrilc)
   ov.protein.impute(adata, method='qrilc', seed=0)

6. 差异分析 —— proDA(直接建模缺失,不需要插补)
   res = ov.protein.de(adata, group='group', method='proda', reference='MB')

PXD000279 教程里这行注释说得很直白 :"drop proteins with too few peptides or too many missing values, median-normalise on the log2 scale, then impute the remaining missing values with QRILC"——QC → normalize → impute,顺序非常明确。

二、为什么必须是"QC → 归一化 → 插补"这个顺序

这不只是 omicverse 的约定,而是 Bioconductor 体系(QFeatures / MSnbase / scp)的一致逻辑 :

  1. QC 过滤必须先做

过滤掉的是:污染物、反向命中、肽段数过低(如 < 2)、在任一组中有效观测比例过低的蛋白

这些蛋白要么不是目标、要么是"数据垃圾",带着它们去做归一化,会污染 median/quantile 的计算基准——median 归一化依赖"大多数蛋白在大多数样本中有观测"这个隐含假设,垃圾蛋白多了,median 本身就偏了

QFeatures 官方流程也是先做 filterFeatures(~ Reverse == "")、filterFeatures(~ Potential.contaminant == ""),再处理缺失值和归一化

  1. 归一化在插补之前

归一化的目的是消掉 run 间的上样量差异(loading effect),让样本间可比

必须在插补前做,因为:

插补算法(特别是 QRILC/MinProb 这类左删失方法)依赖"观测值的分布"来估计截断点。如果数据还没归一化,不同 run 的观测值分布是错位的,截断点估计就错了

median 归一化 + log2 变换让数据近似正态,这是 QRILC 的 truncated normal 分布假设的前提

在 log2 尺度上做插补,随机数注入的"变异"才是生物学意义上合理的(对数线性)

  1. 插补是最后一步

插补是用算法"编造"数据,必须在数据已经被清理、已经被对齐到同一尺度之后才能进行

插补完的数据不再是"原始观测",所以任何后续分析(PCA、差异分析)都必须在插补之后做

三、这套流程"经不经得起考验"
"先诊断缺失机制,再选插补算法"的原则 —— 这是 MSnbase 官方文档明确规定的 :

"MNAR features should ideally be imputed with a left-censor method, such as QRILC... Conversely, it is recommended to use hot deck methods such as nearest neighbours, Bayesian missing value imputation or maximum likelihood methods when values are missing at random."

QRILC 对 MNAR 的有效性 —— PXD000279 是已知的 spike-in benchmark(人类蛋白为背景,E.coli 蛋白按 3:1 比例掺入),ground truth 明确。omicverse 教程在该数据集上验证了:QC → normalize → QRILC 插补后,H/L 两组在 PCA 上沿 PC1 干净分离 ,说明这套流程确实能恢复真实的生物学信号。

proDA 作为差异分析方法 —— proDA 直接对缺失建模,不需要插补步骤,对 3 个生物学重复的小样本更稳健 。

⚠️ 需要警惕的部分

omicverse 的蛋白组学模块是 2.2 版本新上线(2026年5-6月) ,相对年轻。虽然底层插补引擎 pyimputelcmd 是 imputeLCMD 的高保真移植,但 omicverse 自身的 best-practice 流程还需要更多独立论文引用验证。

Bioconductor 官方自己对"高缺失率下插补"是有保留的 :

"Missing value imputation is a sensitive operation... it is likely to dramatically fail when a high proportion of data is missing (10s of %)"

也就是说,如果你的数据总体缺失率 > 30%,插补本身就是危险的——无论 QRILC 还是 KNN。

3 个生物学重复的特殊脆弱性:

min_valid=0.5 意味着一组 3 个重复里至少 2 个有观测才保留。这个条件在 3 重复下其实相当宽松

建议收紧到 min_valid=0.7(3 个里至少 2 个有,且另一组也要有 2 个有),否则插补的"参考点"太弱

五、关于"经不经得起考验"的最终判断

框架经得起考验,具体参数需要自己验证。理由:

✅ "QC → 诊断 → 归一化 → 插补 → 验证"这个顺序:QFeatures 、MSnbase 、scp workshop 、omicverse 四大体系一致,是领域共识

✅ MNAR 用 QRILC/MinProb、MAR 用 KNN/SVD 这个匹配原则:MSnbase 官方文档明文规定

⚠️ QRILC 在你的具体数据上是否最优:需要用 PCA 可视化 + 敏感性分析(换 MinProb 再跑一遍)来验证,不能默认

⚠️ 3 个生物学重复下插补的固有风险:Bioconductor 官方警告过插补在高缺失率下可能"dramatically fail" ,所以 proDA 这种不依赖插补的差异分析方法更值得作为主方案,插补 + DEqMS 作为辅助验证

💡 一个严苛的建议:不要只跑一条管线定生死。同时跑两套:

主方案:QC → 归一化 → proDA(不插补,直接建模缺失)

验证方案:QC → 归一化 → QRILC 插补 → DEqMS

取两套结果的交集作为"高置信差异蛋白",交集之外的标记为"插补敏感"谨慎对待。这是 3 个生物学重复下最稳妥的做法。

import omicverse as ov
import numpy as np

# 0. 载入
adata = ad.AnnData(X=your_df.T)
adata.obs['group'] = ['ctrl']*3 + ['treat']*3

# 1. QC 过滤(先做!)
#   - min_peptides=2: 至少 2 条肽段支撑的蛋白
#   - min_valid=0.7: 收紧阈值,3 重复下至少 2 个有观测
ov.protein.qc_filter(adata, min_peptides=2, min_valid=0.7)

# 2. 缺失机制诊断(归一化之前看!)
mp = ov.protein.missing_pattern(adata)
is_mar, threshold = ov.protein.model_selector(adata)
print(f"MCAR={is_mar}, 删失阈值={threshold:.2f}")
# label-free 数据几乎必然是 MNAR

# 3. 归一化(log2 之前必须 median 对齐)
ov.protein.normalize(adata, method='median', log2=True)

# 4. 插补(MNAR → QRILC)
ov.protein.impute(adata, method='qrilc', seed=0)

# 5. PCA 验证插补效果
ov.protein.pca_plot(adata, color='group', label_samples=True)
# 判读:同组 3 个重复应聚在一起;若分散,插补失败

# 6. 差异分析(小样本 MNAR → proDA)
res_proda = ov.protein.de(adata, group='group', method='proda', reference='ctrl')

# 7. 敏感性分析(强烈建议做)
#   用另一种插补 + 另一种 DE 方法交叉验证
adata2 = adata.copy()
ov.protein.impute(adata2, method='minprob', seed=0)
res_deqms = ov.protein.de(adata2, group='group', method='deqms', reference='ctrl')
# 比较两次差异分析的重叠蛋白,重叠度低的就是"插补敏感"不可靠蛋白
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容