ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

微生物组数据预处理标准化流程:从OTU/ASV过滤到相对丰度转换

微生物组数据预处理标准化流程:从OTU/ASV过滤到相对丰度转换 做微生物组数据分析这几年有一个很深的体会真正决定项目成败的往往不是高端算法或复杂模型而是上游那套看起来平平无奇的“数据预处理”流程。从OTU/ASV过滤到相对丰度转换每一个步骤都暗藏着陷阱稍不留神后面的统计检验、差异分析、机器学习全都会跑偏。这篇内容就围绕我实际项目中反复打磨过的一套标准化流程展开把每一步的“为什么”和“怎么做”都讲清楚希望能给正在被微生物组数据折磨的人一些参考。这套流程适合谁刚接触微生物组数据分析、用QIIME 2或phyloseq做下游分析的人以及已经跑通流程但总觉得结果不稳定、想梳理优化分析方案的研究者。文章不会堆砌理论主要讲实操但每个关键环节都会解释背后的统计学和生物学逻辑确保你能理解每一步的意义而不是盲目照搬代码。1. 内容整体设计与思路拆解1.1 为什么需要一套标准化的预处理流程微生物组数据最典型的特征就是高维、稀疏、成分性。所谓高维通常一个样本里有成千上万个OTU或ASV稀疏指的是绝大多数样本中只有少部分微生物能被检测到很多分类单元在多数样本中丰度为零成分性则是说测序得到的丰度只是相对比例而不是绝对数量各分类单元之间存在“此消彼长”的约束关系。这三个特征叠加导致如果你不做预处理后续分析基本没法看。举个例子如果不过滤低丰度的OTU/ASV那些来自测序错误或污染物的“幽灵分类群”会占据大量特征维度稀释真正有生物学意义的信号。如果不对样本做标准化就直接比较丰度测序深度高的样本天然会“显得”物种更多、丰度更高但这并不是真实的生物学差异只是技术噪声。标准化的预处理流程本质上是在做三件事降噪、降维、可比化。降噪是把可疑的测序错误和污染信号剔除降维是减少下游多重检验的负担提升统计功效可比化则是通过相对丰度等方式让样本之间具有可比性。这三件事做好了后续无论做Alpha多样性、Beta多样性、差异丰度分析还是功能预测结果都会稳健很多。1.2 方案选型OTU还是ASV怎么选才不踩坑开始实际分析前要明确一个基础问题使用OTU还是ASV。这不是一个可以随手选的问题它直接影响后续所有结果的分辨率和可比性。OTUOperational Taxonomic Unit操作分类单元是传统聚类策略的产物通常按97%序列相似度聚类相当于把相似的序列“合并同类项”。优点是兼容性好很多经典数据库和参考文献都基于OTU构建计算资源消耗相对较低。缺点是聚类阈值是人为定义的不同研究之间、不同聚类算法之间差异明显而且聚类过程容易把近缘物种合并丢失细微的生物学差异。ASVAmplicon Sequence Variant扩增子序列变体则走的是“去噪”路子例如DADA2、Deblur这类算法直接把序列解析到单碱基分辨率不需要聚类阈值。优点是分辨率高、可重复性好同一批数据用不同版本软件处理结果依然高度一致跨研究比较也更可靠。缺点是计算开销大对测序质量要求高而且在一些数据库中匹配率可能不如OTU理想。我的建议是除非你要跟历史数据集做严格对比、对方明确使用OTU否则新建项目优先选ASV。理由很直接——ASV在分辨率和可重复性上的优势是OTU无法提供的。而且各个主流流程和数据库对ASV的兼容性已经非常成熟没必要为了保守而牺牲数据质量。1.3 整个流程的核心节点把标准流程拆开核心节点大致是这样特征表生成OTU/ASV表包含每个样本中每个分类单元的序列数特征表过滤剔除低丰度、低流行度的可疑特征样本测序深度检查与最小深度确认标准化与相对丰度转换后续下游分析前的质量核查很多人会把精力全部放在第一步和第五步忽略中间环节。实际上第二步和第四步才是决定分析质量的分水岭。后面我详细展开这两个环节的细节。2. 核心细节解析与实操要点2.1 过滤前先搞清楚你的数据长什么样拿到特征表后不要着急写过滤代码先花点时间把数据的基本盘摸清楚。以R语言phyloseq对象为例我一般会先跑一遍摘要library(phyloseq) ps - readRDS(your_phyloseq_object.rds) ps # phyloseq-class experiment-level object # otu_table() OTU Table: [ 3428 taxa and 120 samples ] # sample_data() Sample Data: [ 120 samples by 8 sample variables ] # tax_table() Tax Table: [ 3428 taxa by 7 taxonomic ranks ]这里能看到总共有多少taxa、多少样本。接下来要检查测序深度分布sample_sums(ps) %% summary() # Min. 1st Qu. Median Mean 3rd Qu. Max. # 10532 25634 35120 40211 49220 120453测序深度的分布很关键。如果有些样本只有几千条序列有些样本有十几万条差异过大的话后续标准化压力会很大而且低深度样本本身的生物信息可信度存疑。此时就要考虑是否剔除极低深度的样本。具体阈值没有绝对标准但有个经验值对16S rRNA基因扩增子测序样本序列数低于5000甚至10000物种组成的稳定性会显著下降。当然这个值还要结合你研究的环境类型、预期物种丰富度来定。比如肠道样本本身复杂度高低深度损失的信息更多极端环境样本复杂度低低深度也可能够用。2.2 低丰度过滤的边界在哪里低丰度过滤是争议最多的环节因为“低”的标准实在模糊。我的思路是分层处理而不是一刀切。首先看绝对丰度。如果某个OTU/ASV在整个数据集中总读数只有个位数比如总共出现2次、3次这种特征极可能来自测序错误或交叉污染。DADA2这类去噪流程已经去除了一部分错误序列但也不能完全排除。把总读数低于某个阈值的特征删掉是常见做法。阈值可以参考总序列数的万分之一也可以根据负对照的结果来确定。其次看流行度prevalence即一个特征在多少比例的样本中出现。如果一个OTU/ASV只在1个样本中出现哪怕丰度不低也可能是罕见污染物或个体偶然携带对群体水平的分析贡献有限还会增加多重检验的负担。实操中我常用的组合是保留至少在5%~10%样本中出现的特征同时去掉绝对总丰度过低的特征。举个具体例子120个样本的数据集我会先筛掉总丰度少于10的特征再筛掉只在5个以下样本中出现的特征。这两个条件组合使用能去掉一大半噪声特征同时保留核心微生物群落信号。2.3 相对丰度转换为什么不是简单的“除以总数”相对丰度转换的常规操作是每个样本中每个特征的读数除以该样本的总读数得到0-100%或0-1的比例。这一步本身不复杂但很多人忽略了背后的两个问题。第一个问题是“闭合效应”closure。一旦转换为相对丰度各特征之间就产生了负相关约束一个特征占比上升其他特征必然下降这不是生物学上的此消彼长而是数学上的强制约束。所以在后续分析中不能直接拿相对丰度去做常规的相关系数分析比如Pearson相关否则容易得到大量虚假相关。第二个问题是方差稳定性。相对丰度数据通常高度偏态优势物种占比高、稀有物种占比极低直接用原始比例做统计检验可能违背正态性假设。这时候需要考虑进一步变换比如CLR中心对数比变换或ILR等距对数比变换这些会在完整标准化方案中用到。所以相对丰度转换要区分场景。如果只是做可视化展示展示群落组成堆叠柱状图、饼图直接按总数缩放没问题。但如果你要用相对丰度做差异检验、相关网络或机器学习就要考虑额外处理比如使用CLR变换后的值。3. 实操过程与核心环节实现3.1 基于phyloseq的特征过滤实操下面是我在实战中反复打磨的一段过滤代码兼顾了低丰度过滤和低流行度过滤library(phyloseq) library(tidyverse) # Step 1: 查看每个特征的总丰度确定合适的绝对丰度阈值 taxa_sums - taxa_sums(ps) summary(taxa_sums) # 常见做法过滤掉总丰度为0的特征偶尔会出现 ps - prune_taxa(taxa_sums(ps) 0, ps) # Step 2: 按最小总丰度过滤 min_total_abundance - 10 ps_filtered - prune_taxa(taxa_sums(ps) min_total_abundance, ps) # Step 3: 按流行度过滤 min_prevalence - 5 # 至少在5个样本中检测到 prev_df - as.data.frame(otu_table(ps_filtered)) prev_count - rowSums(prev_df 0) keep_taxa - prev_count min_prevalence ps_filtered - prune_taxa(keep_taxa, ps_filtered) # 查看过滤前后的变化 ps ps_filtered这段代码的思路很直白先按绝对丰度粗筛再按流行度细筛。在实际项目中我通常会把两个条件做成循环或函数针对不同数据集快速调整参数。有一点要特别提醒如果设置了最小流行度强烈建议结合样本分组来看。比如研究的是疾病vs对照如果某个特征只在疾病组出现、对照完全没有那它对差异分析是有意义的不能因为它总体流行度不高就删掉。所以更稳健的做法是分组计算流行度保留“在任一组中达到流行度阈值”的特征。3.2 使用microbiome包快速实现核心特征筛选如果你想更省事可以直接用microbiome包的core()函数。它的理念就是按流行度和丰度双重阈值筛选核心微生物组代码干净多了library(microbiome) # 将phyloseq对象转换为microbiome可处理的格式 ps_comp - microbiome::transform(ps_filtered, compositional) # 筛选在50%样本中出现且相对丰度不低于0.1%的特征 ps_core - core(ps_comp, detection 0.001, prevalence 0.5) ps_core这里的detection是相对丰度阈值prevalence是样本比例阈值。需要注意transform(ps, compositional)已经做了相对丰度转换所以detection参数用的是比例而不是序列数。这个方案适合快速出结果但如果你的研究需要精细控制还是手动过滤更灵活。3.3 相对丰度转换的标准代码过滤完成后就可以做相对丰度转换了。下面这段代码会把整数值的OTU表转成相对丰度表并同步更新phyloseq对象# 方法一phyloseq自带transform_sample_counts ps_rel - transform_sample_counts(ps_filtered, function(x) x / sum(x)) # 验证转换结果每个样本之和应该为1 otu_rel - otu_table(ps_rel) colSums(otu_rel) %% head() # Sample1 Sample2 Sample3 Sample4 Sample5 Sample6 # 1 1 1 1 1 1 # 方法二如果需要百分数格式0-100 ps_rel_100 - transform_sample_counts(ps_filtered, function(x) x / sum(x) * 100)如果你用的是microbiome包还有一个专门函数ps_rel - microbiome::transform(ps_filtered, compositional)transform(ps, compositional)和transform_sample_counts的差异不大选择哪个顺手即可。注意在相对丰度转换前一定要先完成过滤否则那些低丰度噪声也会被“稀释”到每个样本里只是比例变得很小并不会消失。3.4 要不要做rarefaction稀疏化这是整个流程里最让大家纠结的问题之一。rarefaction稀疏化就是把所有样本统一抽平到相同测序深度比如全部抽到10000条序列多的扔掉少的不足则剔除。以前这是标准操作但现在学术界争议很大。反对rarefaction的理由很充分随机抽平会丢弃有效数据导致统计功效下降同时抽样过程引入新的随机性使结果不稳定不同随机种子可能给出不同结论。而且现代标准化方法如DESeq2的几何均值比率法、edgeR的TMM、以及CLR变换都能更合理地处理测序深度差异。但我个人观点是rarefaction并没有完全过时关键看应用场景。如果你的后续分析手段非常依赖整数值计数比如用vegan做某些多样性指数、用机器学习方法对原始计数敏感那适当rarefaction还能让结果更直观、更容易和旧文献对比。如果是做差异丰度分析我更推荐用专门的工具处理而不是提前rarefaction。如果决定做rarefaction样本最低深度要有数不然会丢掉太多样本。我一般在过滤后先看深度分布用sample_sums()排序确认最小深度和十分位数把明显偏离大部队的低深度样本先剔除再对剩余样本做rarefaction。4. 标准化方案进阶怎么让样本真正可比4.1 相对丰度之外的几种标准化思路标准化的目的是消除测序深度差异带来的技术干扰让样本之间可比。相对丰度转换是最朴素的方式但并不是唯一也不是永远最优。常见的标准化方法大致有几类总丰度缩放TSS也就是相对丰度、累积和缩放CSS、TMM、DESeq2的几何均值比率、以及CLR变换。每种方法背后都有不同的统计假设适用场景也有差异。总丰度缩放就是各样本除以自己的总数简单直观适合粗略比较群落组成但受优势物种影响大。CSS对高丰度物种不敏感它在计算缩放因子时会忽略极高丰度分类群的强烈影响适合宏基因组或高动态范围的扩增子数据。TMM方法常用于转录组它基于加权截断均值对差异物种比例较稳健在扩增子数据中使用需要谨慎。CLR则把每个特征除以其在样本中的几何均值再取对数能有效打破闭合效应适合后续做相关网络、PCA这类依赖于欧氏距离或相关结构的分析。选择标准化方法的核心原则是先明确你要做什么。如果只是看一眼组成比例TSS足够如果要找差异物种DESeq2或edgeR更靠谱如果要算样本间距离、做排序或聚类CLR更加合适。没有“万能方法”只有“适合场景的方法”。4.2 CLR变换实操CLR变换在微生物组分析中越来越常用它的数学定义是对每个样本把每个特征的丰度除以该样本所有特征的几何均值然后取自然对数。用R代码实现可以使用compositions包、microbiome包自带函数library(microbiome) # 先做相对丰度转换再执行CLR ps_clr - microbiome::transform(ps_filtered, clr) # 检验每个样本的CLR值之和应该接近0因为对数比变换的中心化性质 clr_otu - otu_table(ps_clr) rowSums(clr_otu) %% head()注意CLR变换要求所有值都大于0因为对数不能处理0。上游过滤能把一部分零值特点去掉但特征表中依然可能存在大量的0。常用的处理方式有两种给所有0值加一个小的伪计数比如1或者在计算几何均值时只使用非零值。这两种方法各有缺陷前者会引入偏差后者会改变样本间可比性。实际操作中多数人会选择用“乘法替换”方法在矩阵中处理零值也就是把零值替换为一个小值同时调整其他非零值以保持总数不变。比如zCompositions包的cmultRepl()函数就是干这个的。下面是我常用的组合流程library(zCompositions) # 将OTU表转为矩阵并执行乘法零值替换 otu_mat - as.matrix(otu_table(ps_filtered)) otu_repl - cmultRepl(otu_mat, method CZM, output p-counts) # 将替换后的表更新回phyloseq对象 otu_table(ps_filtered) - otu_table(otu_repl, taxa_are_rows TRUE) # 然后再执行CLR ps_clr - microbiome::transform(ps_filtered, clr)这里有个经验点“CZM”方法比简单的加一伪计数更稳健它会基于多项分布生成替换值并重复多次取平均减少单次随机性。但也要注意它比较耗时如果数据很大可以先过滤掉极端低丰度特征减少计算量。4.3 标准化之后的质量核查清单转换完成不等于流程结束我强烈建议在进入下游分析前做一轮质量核查。我的习惯列表如下样本总丰度是否都为1或100如果不是说明转换表/存在非整数计数干扰。聚类/排序前是否重新计算了距离矩阵记得不要再使用原始计数距离。是否检查了特征表中是否存在替换后的负值或NaN有时伪计数处理不当会产生异常值。样本标签是否在过滤后仍然正确样本丢失是常见意外。可以使用简单的可视化来检查批量效应和离群样本library(vegan) # 基于CLR值计算欧氏距离并做PCA排序 dist_clr - vegdist(otu_table(ps_clr), method euclidean) pcoa - cmdscale(dist_clr, k 2) plot(pcoa)如果样本点在PCA图上按照批次聚成清晰的小簇说明批次效应明显需要进一步分析是技术批次还是生物学分组。5. 常见问题与排查技巧实录5.1 过滤后样本数量变少或特征数量变成0这种现象通常有两种原因。第一种是过滤条件过严比如把流行度阈值设成50%以上而你的样本本身来自多个差异巨大的环境组大量特征只在少数样本中出没过滤后特征数骤降。第二种是样本深度过低在过滤低深度样本后剩余样本数不足。排查思路很简单逐步放宽和收紧参数做敏感性分析。比如把流行度阈值从20%降到10%、5%看特征数量变化曲线。如果特征数在某个阈值附近急剧下降说明数据本身就稀疏需要设定更合理阈值如果特征数始终很低可能需要回到上游检查聚类/去噪参数。5.2 相对丰度转换后同一特征在不同样本中差异巨大这有时是真实生物学差异有时是测序深度和样本DNA提取效率导致的伪信号。如果同一批处理的技术重复样本之间相对丰度波动非常大那就要警惕是不是标准化方式选了不合适的。一个常见坑是样本总读数差异特别大比如A样本总读数5万B样本总读数20万经过TSS转换后A样本中的稀有特征可能被放大反而造成“假高丰度”。此时建议考虑不依赖总读数的标准化方法例如TMM或CSS。还有一个容易忽略的问题如果你在过滤前用了不同批次的数据那么批次间测序深度差异会在标准化后依然残留。建议在准备数据时先按批次和样本类型做好分层或使用R包如sva的ComBat_seq做批次校正再去标准化。5.3 用相对丰度直接做相关分析得出的“共现网络”可能是假的我在实际项目中踩过最大的坑就是直接用相对丰度计算Spearman相关然后构建物种共现网络。结果出现了大量正相关初看很兴奋结果发现很多相关性是闭合效应逼出来的。比如样本中物种A占比从40%降到20%那么其他所有物种的总占比自动升高了哪怕它们之间毫无生物学关联也会产生负相关或正相关。要正确处理应该用CLR变换后的数值做相关分析至少也要做成分数据感知的相关方法比如SparCC或Propr。另外提醒一句CLR或ILR变换后相关性解释要更谨慎因为其尺度是对数空间数值大小不能直接按原始丰度理解。5.4 汇总成问题速查表常见问题可能原因推荐处理方式特征数过低过滤阈值过高、数据稀疏逐步降低阈值做敏感性分析样本总丰度和不为1使用了整数值表未转换重新执行TSS并检查行列方向CLR后出现NaN存在零值使用乘法替换或伪计数处理零值样本聚类按批次分开批次效应明显分层抽样、批次校正后再分析相对丰度相关网络假阳性多闭合效应使用CLR或SparCC等方法稀有物种对结果影响过大未过滤低丰度特征先过滤再标准化6. 实操心得与一个容易被忽略的提升方向最后聊一些不常出现在教程里、但直接影响体验和结果的事情。第一点是记录所有参数。过滤阈值、深度处理规则、标准化方法、随机种子全都要记录下来。很多项目做到后期需要复现结果、回应对审稿人的质疑如果没有详细参数记录返工成本极高。建议在分析项目里建一个parameters.yaml或者简单的备忘文本把每一步的代码版本、参数、日期写清楚。第二点是所有转换步骤都尽量保留原始数据不可变。我习惯把上游生成的原始特征表单独存档任何过滤和转换都只生成新对象绝不原地覆盖。这样如果后续需要调整阈值或者换一种标准化方法随时可以回到干净起点。第三点值得一提的高级技巧可以把过滤和标准化封装成一个函数输入原始phyloseq对象和参数列表输出预处理后的对象和摘要报告。这样在多组数据、多轮分析中保持一致减少人为误差。下面是我的简化模板preprocess_ps - function(ps, min_total_abundance 10, min_prevalence_samples 5, norm_method compositional) { # 过滤零丰度 ps - prune_taxa(taxa_sums(ps) 0, ps) # 总丰度过滤 ps - prune_taxa(taxa_sums(ps) min_total_abundance, ps) # 流行度过滤 prev_count - rowSums(otu_table(ps) 0) ps - prune_taxa(prev_count min_prevalence_samples, ps) # 标准化 if (norm_method compositional) { ps - transform_sample_counts(ps, function(x) x / sum(x)) } else if (norm_method clr) { # 这里省略零值处理细节实际需要先替换零值 ps - microbiome::transform(ps, clr) } return(ps) }在实际操作中我吃过不少亏比如发现共享同一批数据的不同文章因预处理参数不同导致重叠物种数量差异巨大也见过因为标准化方式没写清楚审稿人要求重跑所有分析的窘境。所以在这篇实战记录里我尽可能把每一步的细节和考虑都摊开来写。预处理是微生物组分析中最不显眼但最值得花心思的环节把它做扎实下游分析才会真正站得住脚。
返回列表