物种丰度数据格式解读:OTU表、ASV表、BIOM格式及元数据文件

做宏基因组分析,第一步就是跟数据格式打交道。很多新手拿到 OTU 表手忙脚乱,其实说白了,这些格式就是给物种计数搭了个架子。我个人习惯先理清三种主流格式——OTU 表、ASV 表、BIOM 格式——再加上配套的元数据文件。搞懂它们,后面的分析才能跑起来。这章我带你从头拆一遍。

OTU 表:最经典的物种丰度矩阵

OTU(Operational Taxonomic Unit)表是宏基因组分析的老牌格式。每一行代表一个分类单元(通常按 97% 序列相似度聚类),每一列代表一个样本,单元格里是序列计数或者相对丰度。你想想看,一个标准的 OTU 表长这样:

OTU_ID     Sample1  Sample2  Sample3  ...
OTU_1       120       85      203
OTU_2        45      112       67
OTU_3       678      234      890
...

表格第一列是 OTU 编号,后面每列都是一个样本。行列顺序无所谓,但千万别丢了 OTU_ID 这一列。我记得有次项目里同事把第一列当成了普通数据,结果后面聚类分析全是错的。

我的一点习惯:把 OTU 表存成 CSV 或 TSV,用 R 的 read.csv() 或 readr::read_tsv() 读入时,记得指定 row.names = 1。这样 OTU_ID 自动变成行名,方便后续转矩阵。

ASV 表:更高精度的替代方案

这几年 ASV(Amplicon Sequence Variant)越来越流行。DADA2、Deblur 这类工具直接对扩增子序列进行单碱基分辨率的去噪,不再聚到 97% OTU。ASV 表的格式和 OTU 表一模一样,只是行名变成了 ASV_1 或实际序列哈希值。好处是分辨率更高,但稀疏性也更强。

我曾经踩过一个坑:用 DADA2 产出 ASV 表后,直接当 OTU 表往下游分析,结果在 diversity 计算时内存爆了。原因是 ASV 的行数可能是 OTU 的 5~10 倍。如果你拿到 ASV 表,我建议先了解数据量,再决定要不要合并成 OTU 做降维。

BIOM 格式:结构化生态数据标准

BIOM(Biological Observation Matrix)是 QIIME、MG-RAST 等工具通用的标准格式。它本质是一个 JSON(或 HDF5)文件,把观测表、样本元数据、特征元数据打包在一起。你不用自己手动拼,但得能看懂它的结构。

一个简化的 BIOM 片段(JSON 格式)长这样:

{
  "id": "MyStudy",
  "format": "Biological Observation Matrix 1.0.0",
  "matrix_type": "sparse",
  "shape": [3, 4],
  "rows": [
    {"id": "OTU_1", "metadata": {"taxonomy": ["Bacteria","Firmicutes"]}},
    {"id": "OTU_2", "metadata": {"taxonomy": ["Bacteria","Bacteroidetes"]}},
    {"id": "OTU_3", "metadata": {"taxonomy": ["Bacteria","Proteobacteria"]}}
  ],
  "columns": [
    {"id": "Sample1", "metadata": {"treatment":"control"}},
    {"id": "Sample2", "metadata": {"treatment":"drought"}},
    {"id": "Sample3", "metadata": {"treatment":"control"}},
    {"id": "Sample4", "metadata": {"treatment":"drought"}}
  ],
  "data": [[0,0,120],[0,1,45],[0,2,678],[1,0,85],[1,1,112],[1,2,234],
           [2,0,203],[2,1,67],[2,2,890],[3,0,55],[3,1,99],[3,2,444]]
}

rows 是特征(OTU/ASV),columns 是样本,data 用稀疏格式存储非零值。BIOM 文件可以从 QIIME2 导出,R 里用 biomformat 包或 phyloseq::import_biom() 读取。我个人偏好先转成 phyloseq 对象,后面分析更顺。

注意版本:BIOM 1.0 和 BIOM 2.1(HDF5)不兼容。QIIME2 默认生成 2.1,但某些旧包只认 1.0。如果你在 R 里读报错,试试 qiime tools export 转成 1.0 格式。

元数据文件:分析成败的基石

元数据(metadata)就是样本的“身份证”。每行一个样本,每列一个变量,比如组别、时间、个体ID。一定要有第一列 SampleID,且必须和丰度表的列名一一对应。我见过最坑的是列名大小写不一致,导致合并时全部 NA。

一个标准的元数据文件:

SampleID    Condition  Time  Weight
Sample1     Control     Day0   25.3
Sample2     Drought     Day0   24.8
Sample3     Control     Day7   26.1
Sample4     Drought     Day7   23.9

在 R 里用 read.csv() 读入,然后 dplyr::left_join() 或 phyloseq::sample_data() 关联。记住:元数据不能有空格或特殊符号,列名最好用英文加下划线,省得后面绘图报错。

格式对比速查表

格式主要用途结构特点常见来源R 读取方式
OTU 表经典聚类丰度矩阵行=OTU,列=样本,数值计数USEARCH, VSEARCHread.csv(),指定行名
ASV 表去噪后高精度矩阵行=ASV,列=样本,数值计数DADA2, Deblurread.csv(),指定行名
BIOM 格式标准化打包存储JSON/HDF5 含观测+元数据QIIME2, MG-RASTbiomformat::read_biom() / phyloseq::import_biom()
元数据文件样本分组与属性行=样本,列=变量,第一列 SampleID手动整理read.csv(),合并时注意列名类型

数据格式关系图

下面这张图可以帮你快速理解四种数据格式的关联与流向。

宏基因组物种丰度数据格式关系 物种丰度数据(主表) OTU 表 ASV 表 BIOM 格式 元数据文件 所有格式都可以转换到中心丰度表, 配合元数据后用于下游分析与可视化。

核心经验:拿到数据后,我先检查一下文件头几行。OTU/ASV 表确认第一列是 ID,BIOM 文件用 R 的 jsonlite::fromJSON() 瞥一眼结构,元数据确认 SampleID 列名没有空格和点。这些习惯能省掉后面 80% 的出错排查时间。

避坑指南

格式转换时,最容易翻车的点:

  • BIOM 的 columns 中 id 必须和元数据的 SampleID 完全匹配,包括大小写和特殊符号。
  • OTU 表如果含有 NA、空值或负值,一定要提前处理,否则 phyloseq 会报错。
  • 元数据文件不要有隐藏的空格或不可见字符。我习惯用 readr::read_csv() 代替 read.csv(),因为前者能自动识别编码和 trim_ws。
又一个血的教训:我曾经用 Excel 编辑过 BIOM 文件内的 JSON 数据,保存后 Excel 自动把引号变弯引号,导致整个文件解析失败。处理结构化数据,还是用纯文本编辑器(比如 VS Code、Sublime)更安全。

好了,这四种格式是后续所有分析的基础。你只要把 OTU/ASV 表和元数据理顺,剩下的就是用 R 把它们喂给各种函数。我自己现在基本只用 phyloseq 统一管理,但脑子里始终清楚这些原始格式长什么样,因为调试时常常需要直接看 raw data。