资讯详情

Swarm聚类实战:16S扩增子测序OTU分析从原理到参数调优

📅 2026/10/15 11:17:47 | 华诺云谱 👁 阅读
Swarm聚类实战:16S扩增子测序OTU分析从原理到参数调优
1. 为什么还要聊 Swarm 这个老家伙16S 扩增子测序分析这条流水线上OTU 聚类一直是绕不开的一环。早些年大家默认用 97% 相似度切 OTU工具换来换去无非是 QIIME 里那套 pick_otus 或者 UPARSE。但如果你做过几年微生物多样性项目就会发现一个很现实的问题97% 这个阈值本身是个人为设定的经验值它既不能反映真实的物种边界也会把一些亲缘关系很近但生态功能完全不同的菌混在一起。Swarm 就是在这个背景下被一批做微生物生态的人推出来的它的核心卖点很直接——不设固定阈值让序列自己抱团。我第一次接触 Swarm 是在一个土壤微生物的项目里当时用 UPARSE 跑出来的 OTU 数量比预期少了一大截稀释曲线早早饱和导师看了一眼就说你这聚类聚得太狠了。后来换成 Swarm 的默认参数重跑OTU 数量上去了低丰度类群的多样性也保留得更好。从那以后Swarm 就成了我处理 16S 数据时的一个常备选项。这篇文章面向的是已经跑过 16S 基本流程、对 OTU/ASV 有概念、想尝试 Swarm 或者正在被聚类参数折磨的人。我会把 Swarm 的原理、安装、完整实操流程、参数调优、踩过的坑都摊开讲一遍尽量做到你照着做就能跑通自己的数据。文章里涉及的命令和参数都是我在实际项目里验证过的不是从文档里抄一遍了事。2. Swarm 到底在干什么原理与设计思路拆解2.1 从固定阈值到自然聚类的转变传统 OTU 聚类的逻辑是先设定一个相似度阈值通常是 97%然后把所有两两相似度高于这个阈值的序列归为一类。这个做法的问题在于阈值是全局统一的但微生物 16S 基因的进化速率并不是均匀的。有些属内不同种的 16S 相似度可能高达 99%有些属间却只有 95%。一刀切的结果就是有的 OTU 里塞了几十个不同的种有的种却被拆成了好几个 OTU。Swarm 的思路完全不同。它采用一种叫局部聚类的策略先把序列按丰度从高到低排序然后以每条高丰度序列为种子把与它相似度超过某个初始阈值默认 d1即允许 1 个碱基差异的序列吸进来形成一个小集群。接着这个集群会继续向外扩展把与集群内任意序列相似度满足条件的序列也拉进来直到没有新序列可以加入为止。这个过程像滚雪球一样最终形成的每个 OTU 内部的序列差异是自然生长出来的而不是被一个预设阈值框死的。注意Swarm 的 d1 指的是允许 1 个碱基的差异不是 1% 的差异。对于 16S V4 区约 250bp 的序列来说1 个碱基差异大约相当于 99.6% 的相似度这比传统的 97% 严格得多。2.2 为什么 Swarm 能保留更多低丰度多样性这里要讲一个很多人忽略的点Swarm 的聚类顺序是按丰度降序进行的。高丰度序列先形成种子集群低丰度序列在后续过程中被分配到已有的集群或者形成新的小集群。这种丰度优先的策略有两个好处一是高丰度序列通常代表真实存在的优势物种以它们为种子更可靠二是低丰度序列不会被强行塞进一个不相关的优势 OTU 里而是有机会形成自己的小集群从而保留了稀有类群的信号。我在一个肠道菌群项目里做过对比同一批数据UPARSE 跑出 1200 个 OTUSwarm 默认参数跑出 2800 多个。稀释曲线显示 Swarm 的结果在测序深度范围内还没有完全饱和说明它确实挖掘出了更多低丰度类群。当然这不意味着 OTU 越多越好后面还要做去噪和过滤但至少 Swarm 给了你保留这些信息的可能性。2.3 Swarm 的两种运行模式fastidious 与 non-fastidiousSwarm 提供了两种聚类模式这是新手最容易搞混的地方。non-fastidious 模式默认只做一轮聚类速度快适合大规模数据快速处理。它的逻辑就是前面说的滚雪球简单直接。fastidious 模式加-f参数则是在第一轮聚类完成后再做一轮精修。具体来说它会检查那些在第一轮中因为与任何种子序列差异都超过 d1 而未能加入任何集群的序列尝试把它们分配到已有的 OTU 中条件是这些序列与某个 OTU 的代表序列差异不超过一个更宽松的阈值默认 d2。这个模式能进一步减少 OTU 数量提高聚类的完整性但计算量会明显增加。我的经验是如果数据量在百万条序列以内直接用 fastidious 模式结果更干净如果数据量很大或者只是做初步探索先用 non-fastidious 跑一版看看分布。3. 跑通 Swarm 之前环境准备与数据预处理3.1 安装 Swarm 的几种方式与选择建议Swarm 的安装不算复杂但有几个坑我踩过这里直接说结论。方式一源码编译。从官方仓库下载源码用./autogen.sh ./configure make编译。这种方式最灵活但依赖 autoconf、automake、g 等工具链在干净的服务器上可能要折腾一会儿。我遇到过因为 g 版本太老导致编译失败的情况升级编译器后解决。方式二conda 安装。conda install -c bioconda swarm是最省事的方式bioconda 上的版本更新也比较及时。但要注意 conda 环境的隔离避免和系统里的其他工具冲突。我一般会为 16S 分析单独建一个环境把 Swarm、VSEARCH、QIIME 2 的依赖都装进去。方式三Docker 镜像。如果你不想动服务器环境用 Docker 跑 Swarm 是最干净的。官方和社区都有维护的镜像挂载数据目录就能用。适合在共享服务器上不想污染环境的情况。提示无论哪种方式安装完后用swarm --version确认一下版本。不同版本在参数默认值和输出格式上可能有细微差异建议在文章或项目记录里注明版本号。3.2 输入文件的格式要求与常见错误Swarm 的输入文件要求是FASTA 格式而且序列需要预先做过去冗余dereplication和排序。具体来说每条序列的 ID 后面要带上丰度信息格式通常是seqID;sizeN或者seqID_abundanceN。Swarm 会解析这个丰度值用于排序。序列需要按丰度降序排列。虽然 Swarm 内部也会排序但预先排好可以节省时间。序列长度要一致或者经过对齐修剪。Swarm 本身不做对齐它依赖的是序列之间的编辑距离所以输入序列最好是等长的比如都修剪到 V4 区的 250bp。我见过最常见的错误是直接把原始测序数据丢给 Swarm。原始数据里有引物、有低质量碱基、有嵌合体这些都会严重影响聚类结果。正确的做法是先经过质控、去引物、去嵌合、去冗余得到干净的 unique 序列再喂给 Swarm。3.3 用 VSEARCH 做预处理的完整命令虽然 Swarm 官方推荐用它的配套工具但我习惯用 VSEARCH 做预处理因为速度快、参数直观。下面是我常用的一套命令假设你已经有双端测序数据sample_R1.fastq和sample_R2.fastq# 1. 合并双端序列 vsearch --fastq_mergepairs sample_R1.fastq \ --reverse sample_R2.fastq \ --fastqout merged.fastq \ --fastq_minovlen 20 \ --fastq_maxdiffs 5 # 2. 质量过滤 vsearch --fastq_filter merged.fastq \ --fastq_maxee 1.0 \ --fastq_minlen 200 \ --fastaout filtered.fasta # 3. 去冗余 vsearch --derep_fulllength filtered.fasta \ --sizeout \ --output uniques.fasta # 4. 去嵌合体需要参考数据库这里以 RDP 为例 vsearch --uchime_ref uniques.fasta \ --db rdp_gold.fasta \ --nonchimeras clean.fasta \ --sizeout # 5. 按丰度排序 vsearch --sortbysize clean.fasta \ --output sorted.fasta这几步跑完sorted.fasta就是可以直接喂给 Swarm 的输入文件。注意--sizeout参数会把丰度信息写入序列 IDSwarm 需要这个信息。注意--fastq_maxee 1.0这个阈值比较严格适合高质量数据。如果你的数据质量一般可以放宽到 2.0 或 3.0但要注意会引入更多噪声。4. Swarm 聚类实操从命令到结果解读4.1 基础聚类命令与参数详解最基础的 Swarm 命令长这样swarm -d 1 -f -t 8 sorted.fasta \ -o swarm_otus.txt \ -w swarm_representatives.fasta逐个参数解释-d 1初始聚类阈值允许 1 个碱基差异。这是默认值一般不需要改。如果你做的是 ITS 区域或者差异较大的基因可以适当放宽到 2 或 3。-f启用 fastidious 模式。前面说过数据量不大时建议开启。-t 8使用 8 个线程。Swarm 支持多线程根据你的服务器核数调整。我一般设成物理核数的一半留点资源给系统。-o swarm_otus.txt输出 OTU 列表文件每行是一个 OTU包含属于该 OTU 的所有序列 ID。-w swarm_representatives.fasta输出每个 OTU 的代表序列通常是丰度最高的那条。跑完之后你会得到两个核心文件swarm_otus.txt和swarm_representatives.fasta。前者用于后续的 OTU 表构建后者用于物种注释。4.2 输出文件的结构与含义swarm_otus.txt的格式很简洁每行以 OTU 代表序列 ID 开头后面跟着属于该 OTU 的其他序列 ID用空格分隔。比如seq1;size1500 seq5;size200 seq12;size50 seq2;size800 seq7;size120 seq3;size600第一行表示 seq1 是代表序列seq5 和 seq12 被聚到了这个 OTU 里。注意 Swarm 不会给 OTU 编号你需要自己加一个 OTU ID比如 OTU_1、OTU_2这个在后续用 QIIME 或 phyloseq 分析时需要。swarm_representatives.fasta里就是每个 OTU 的代表序列可以直接拿去做物种注释。我一般用 SILVA 或 Greengenes 数据库通过 QIIME 2 的feature-classifier或者 VSEARCH 的--usearch_global做比对。4.3 从 Swarm 输出到 OTU 表的转换Swarm 本身不生成 OTU 表你需要自己转换。最直接的方法是用一个脚本把swarm_otus.txt和原始样本的序列对应关系结合起来。如果你用的是 QIIME 2可以把 Swarm 的结果导入为FeatureData[Sequence]和FeatureTable[Frequency]。我常用的一个转换思路是先用biom convert或者 QIIME 2 的import命令把代表序列和 OTU 列表导入然后用vsearch --usearch_global把原始样本的序列比对到代表序列上统计每个样本中每个 OTU 的丰度。这个过程听起来绕但跑通了就很顺。提示如果你不想自己写脚本可以看看 Swarm 官方配套的swarm_utils或者一些第三方脚本社区里有人分享过转换工具。但要注意版本兼容性别直接用来源不明的脚本处理重要数据。5. 参数调优与常见问题排查5.1 d 值怎么选不是越大越好-d参数是 Swarm 最核心的调节旋钮。默认 d1 适合大多数 16S 数据但有些情况需要调整数据噪声大如果测序质量差d1 可能会把同一物种的序列拆成多个 OTU。这时候可以试试 d2但要注意会合并一些真实的不同物种。目标区域变异大比如 ITS 区域种间差异可能达到几个碱基d1 太严格d3 或 d4 更合适。做精细分析如果你想区分到种甚至株水平d1 甚至 d0完全相同的序列才聚在一起更合适。我的建议是先用 d1 跑一版看看 OTU 数量分布和稀释曲线再决定要不要调整。不要一上来就改参数否则你很难判断结果差异是参数导致的还是数据本身的问题。5.2 常见报错与解决方法报错信息可能原因解决方法Error: sequence length differs输入序列长度不一致用vsearch --fastq_filter或cutadapt统一修剪长度Error: invalid abundance format序列 ID 里没有丰度信息检查去冗余步骤是否加了--sizeoutSegmentation fault内存不足或序列数过多增加内存或先用 non-fastidious 模式跑No such file or directory输入文件路径错误用绝对路径检查文件权限输出文件为空输入序列太少或全部被过滤检查预处理步骤确认有序列通过质控5.3 性能优化让 Swarm 跑得更快Swarm 的计算复杂度主要取决于序列数量和序列之间的差异。几个提速技巧增加线程数-t参数直接控制并行度在服务器上尽量用满。先用 non-fastidious 模式如果只是探索性分析先跑 non-fastidious确认数据没问题再跑 fastidious。减少输入序列数通过更严格的质控和去冗余把 unique 序列数降下来。我一般会把丰度低于 2 的序列先过滤掉这些序列对聚类结果影响很小但会显著增加计算量。使用 SSD 存储Swarm 的 I/O 也比较重输入输出文件放在 SSD 上比机械硬盘快很多。6. 我踩过的坑与实操心得6.1 不要跳过预处理直接聚类这是我早期犯的最大错误。当时觉得 Swarm 反正会自己处理就把原始数据稍微过滤了一下直接丢进去。结果跑出来的 OTU 数量爆炸稀释曲线完全没饱和后来发现是嵌合体和测序错误被当成了真实序列。预处理这一步省不得尤其是去嵌合体。嵌合体序列往往介于两个真实序列之间Swarm 的局部聚类很容易把它们吸进某个 OTU导致 OTU 内部差异异常大。6.2 代表序列的选择会影响物种注释Swarm 默认选丰度最高的序列作为代表序列这通常没问题。但如果你发现某个 OTU 的物种注释结果很奇怪可以检查一下代表序列是不是一条质量较差的序列。有时候丰度最高的序列恰好有测序错误用它去比对数据库就会得到错误的结果。这种情况下可以手动把代表序列换成 OTU 中与数据库匹配最好的那条。6.3 结果的可重复性依赖版本和参数Swarm 的不同版本在聚类逻辑上有细微调整同一个数据集在不同版本下跑出来的 OTU 数量可能差几百个。所以在项目记录里一定要写清楚 Swarm 版本号和所有参数。我现在的习惯是每次跑完都把命令和版本信息写进一个README文件方便以后复现。6.4 与其他工具的衔接Swarm 的输出可以无缝衔接到 QIIME 2、phyloseq、Mothur 等下游工具。我一般用 QIIME 2 做后续的多样性分析和统计检验因为它的可视化比较方便。如果你习惯用 R把 OTU 表和代表序列导入 phyloseq 也很直接。关键是确保 OTU ID 和样本 ID 的对应关系正确这个在手动转换时容易出错。7. 一个完整的 Swarm 分析流程示例7.1 从原始数据到 OTU 表的全流程假设你有 10 个样本的双端测序数据放在raw_data/目录下样本名为 S1 到 S10。下面是我常用的完整流程# 创建输出目录 mkdir -p results/01_merge results/02_filter results/03_derep results/04_chimera results/05_swarm # 对每个样本循环处理 for sample in S1 S2 S3 S4 S5 S6 S7 S8 S9 S10; do # 合并双端 vsearch --fastq_mergepairs raw_data/${sample}_R1.fastq \ --reverse raw_data/${sample}_R2.fastq \ --fastqout results/01_merge/${sample}_merged.fastq \ --fastq_minovlen 20 \ --fastq_maxdiffs 5 # 质量过滤 vsearch --fastq_filter results/01_merge/${sample}_merged.fastq \ --fastq_maxee 1.0 \ --fastq_minlen 200 \ --fastaout results/02_filter/${sample}_filtered.fasta done # 合并所有样本 cat results/02_filter/*_filtered.fasta results/02_filter/all.fasta # 去冗余 vsearch --derep_fulllength results/02_filter/all.fasta \ --sizeout \ --output results/03_derep/uniques.fasta # 去嵌合体 vsearch --uchime_ref results/03_derep/uniques.fasta \ --db rdp_gold.fasta \ --nonchimeras results/04_chimera/clean.fasta \ --sizeout # 排序 vsearch --sortbysize results/04_chimera/clean.fasta \ --output results/05_swarm/sorted.fasta # Swarm 聚类 swarm -d 1 -f -t 16 results/05_swarm/sorted.fasta \ -o results/05_swarm/otus.txt \ -w results/05_swarm/representatives.fasta这套流程跑完results/05_swarm/目录下就是最终的 OTU 列表和代表序列。7.2 结果验证怎么判断聚类是否合理跑完 Swarm 后我一般会做几个检查OTU 数量和预期范围对比。16S V4 区土壤样本通常几千个 OTU肠道样本几百到一千多。如果数量异常多或异常少要排查原因。OTU 大小分布画一个 OTU 丰度 rank-abundance 曲线。健康的分布应该是少数 OTU 占主导大量 OTU 低丰度曲线呈长尾状。代表序列长度检查代表序列长度是否一致有没有异常短的序列。稀释曲线用 QIIME 2 或 R 画稀释曲线看是否趋于饱和。如果远未饱和可能需要增加测序深度或检查预处理是否过度过滤。7.3 下游分析衔接拿到 OTU 表和代表序列后下一步通常是物种注释用 QIIME 2 的feature-classifier classify-sklearn或 VSEARCH 比对 SILVA 数据库。构建系统发育树用mafft对齐代表序列fasttree建树用于后续的 UniFrac 分析。多样性分析计算 alpha 多样性Shannon、Chao1和 beta 多样性Bray-Curtis、UniFrac做 PCoA 或 NMDS 可视化。差异丰度分析用 DESeq2、ANCOM 或 LEfSe 找组间差异显著的 OTU。这些步骤和用其他工具跑出来的 OTU 表没有本质区别关键是确保 OTU ID 和样本 ID 的映射正确。8. 关于 Swarm 的一些个人看法Swarm 不是万能的。它的优势在于不依赖固定阈值能保留更多自然多样性尤其适合探索性研究和低丰度类群的分析。但它的缺点也很明显计算量比 UPARSE 大OTU 数量偏多导致下游统计检验的多重比较负担重而且不同版本之间的结果可重复性需要额外注意。我现在的工作流是先用 Swarm 跑一版看整体多样性再用 ASV 方法如 DADA2 或 UNOISE3跑一版做精细分析。两者互为补充Swarm 帮你发现可能被 ASV 过滤掉的稀有类群ASV 帮你获得更干净、更可解释的物种单元。如果你时间有限只能选一个那就看你的研究问题关注整体群落结构用 Swarm关注具体物种差异用 ASV。最后分享一个小技巧Swarm 跑完后别急着删中间文件。尤其是sorted.fasta和uniques.fasta后面如果发现聚类结果有问题可以快速回溯到某一步重新跑不用从头再来。我一般会把整个流程的中间文件保留至少一个月等文章投出去再清理。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑