跳转至

630_基因组去污染Decontam

一句话概述: 实验室试剂和环境中的微生物DNA会严重污染低生物量样本(如皮肤、空气、血液)的微生物组数据,decontam是R/Bioconductor包通过频率法和流行度法识别污染物,micRoclean(2025年发布)则专门针对宏基因组组装后的MAG去污染。

核心知识点速查表

概念白话解释
Contamination污染——样本中混入了不是来自研究对象的微生物DNA
Kitome试剂盒污染——DNA提取试剂自带的微生物DNA
Negative control阴性对照——不加样本的空白提取(检测试剂污染)
Frequency method频率法——污染物在高DNA浓度样本中占比低
Prevalence method流行度法——污染物在阴性对照中更常见
decontamR包,用统计方法识别和去除污染序列
micRoclean2025年新工具,用于MAG去污染
DNA concentrationDNA浓度——样本总DNA量(频率法的关键输入)
Low biomass低生物量——微生物含量很少的样本类型

一、安装

# === decontam安装(Bioconductor)===
if (!require("BiocManager")) install.packages("BiocManager")
BiocManager::install("decontam")  # 安装decontam

# === 依赖包 ===
BiocManager::install("phyloseq")   # 微生物组数据管理
install.packages("ggplot2")        # 可视化
install.packages("gridExtra")      # 图形排列

library(decontam)   # 加载decontam
library(phyloseq)   # 加载phyloseq
library(ggplot2)    # 加载ggplot2

二、数据准备

2.1 构建phyloseq对象

# === 准备输入数据 ===
# decontam需要:
# 1. ASV/OTU丰度表
# 2. 样本元数据(含DNA浓度和/或阴性对照标记)
# 3. 分类注释(可选但推荐)

# 读取数据
otu <- read.csv("otu_table.csv", row.names = 1)  # OTU表
tax <- read.csv("taxonomy.csv", row.names = 1)    # 分类表
meta <- read.csv("sample_metadata.csv", row.names = 1)  # 元数据

# 元数据必须包含:
# DNA_concentration — DNA浓度(ng/µL),频率法需要
# is_neg — 是否是阴性对照(TRUE/FALSE),流行度法需要

# 构建phyloseq对象
ps <- phyloseq(
    otu_table(as.matrix(otu), taxa_are_rows = TRUE),  # OTU表
    tax_table(as.matrix(tax)),                          # 分类表
    sample_data(meta)                                   # 元数据
)

cat("样本数:", nsamples(ps), "\n")
cat("特征数:", ntaxa(ps), "\n")
cat("阴性对照数:", sum(sample_data(ps)$is_neg), "\n")

2.2 数据质量检查

# === 检查DNA浓度分布 ===
df <- data.frame(sample_data(ps))  # 提取元数据

# 画DNA浓度分布
ggplot(df, aes(x = DNA_concentration, fill = is_neg)) +
    geom_histogram(bins = 30, alpha = 0.7, position = "identity") +
    scale_fill_manual(values = c("FALSE" = "steelblue", "TRUE" = "red"),
                      labels = c("Sample", "Negative Control")) +
    labs(x = "DNA Concentration (ng/µL)", 
         y = "Count",
         title = "DNA Concentration Distribution",
         fill = "Sample Type") +
    theme_minimal()

ggsave("dna_concentration_dist.pdf", width = 8, height = 5)

# === 检查阴性对照中的reads数 ===
neg_samples <- sample_names(ps)[sample_data(ps)$is_neg == TRUE]
neg_reads <- sample_sums(ps)[neg_samples]
cat("阴性对照reads数:\n")
print(neg_reads)

# 如果阴性对照reads太少(<100),流行度法可能不可靠
# 如果阴性对照reads太多(>10000),说明污染严重

三、频率法(Frequency Method)

3.1 基本用法

# === 频率法:利用DNA浓度识别污染物 ===
# 原理:真正的微生物在所有样本中的频率不随DNA浓度变化
#       污染物的频率随DNA浓度增加而降低(因为被稀释了)

contamdf_freq <- isContaminant(
    ps,                            # phyloseq对象
    method = "frequency",          # 使用频率法
    conc = "DNA_concentration",    # DNA浓度列名
    threshold = 0.1                # 阈值(p<0.1视为污染物)
)

# 查看结果
table(contamdf_freq$contaminant)  # TRUE=污染物, FALSE=非污染物
cat("识别的污染物数:", sum(contamdf_freq$contaminant), "\n")

# 阈值选择:
# 0.1 — 默认值,较保守
# 0.5 — 更积极去除污染(可能误伤真实微生物)
# 0.05 — 非常保守(可能漏掉污染物)

3.2 可视化频率模式

# === 可视化:污染物vs真实微生物的频率模式 ===
# 选几个疑似污染物看频率-浓度关系

# 找到所有被标记为污染物的ASV
contam_asvs <- rownames(contamdf_freq[contamdf_freq$contaminant == TRUE, ])

# 画频率-浓度图(前6个污染物)
plot_frequency(
    ps,                            # phyloseq对象
    taxa = head(contam_asvs, 6),   # 展示前6个污染物
    conc = "DNA_concentration"     # DNA浓度列
) + 
    labs(title = "Contaminant Frequency vs DNA Concentration")

ggsave("contaminant_frequency.pdf", width = 12, height = 8)

# 解读:
# 污染物:频率随DNA浓度增加而下降(负相关)
# 真实微生物:频率不随DNA浓度变化(无相关)

四、流行度法(Prevalence Method)

4.1 基本用法

# === 流行度法:利用阴性对照识别污染物 ===
# 原理:污染物在阴性对照中出现的频率>在真实样本中出现的频率

contamdf_prev <- isContaminant(
    ps,                            # phyloseq对象
    method = "prevalence",         # 使用流行度法
    neg = "is_neg",                # 阴性对照标记列名
    threshold = 0.1                # 阈值
)

table(contamdf_prev$contaminant)  # 查看结果
cat("识别的污染物数:", sum(contamdf_prev$contaminant), "\n")

4.2 可视化流行度模式

# === 可视化流行度比较 ===
# 计算每个ASV在阴性对照和真实样本中的流行度
ps_neg <- prune_samples(sample_data(ps)$is_neg == TRUE, ps)   # 阴性对照
ps_pos <- prune_samples(sample_data(ps)$is_neg == FALSE, ps)  # 真实样本

# 流行度数据框
prev_df <- data.frame(
    prev_neg = apply(otu_table(ps_neg), 1, function(x) sum(x > 0)),
    prev_pos = apply(otu_table(ps_pos), 1, function(x) sum(x > 0)),
    contaminant = contamdf_prev$contaminant
)
prev_df$prev_neg_frac <- prev_df$prev_neg / nsamples(ps_neg)
prev_df$prev_pos_frac <- prev_df$prev_pos / nsamples(ps_pos)

# 画散点图
ggplot(prev_df, aes(x = prev_neg_frac, y = prev_pos_frac, 
                     color = contaminant)) +
    geom_point(alpha = 0.6, size = 2) +
    geom_abline(slope = 1, intercept = 0, linetype = "dashed") +
    scale_color_manual(values = c("FALSE" = "grey60", "TRUE" = "red"),
                       labels = c("Non-contaminant", "Contaminant")) +
    labs(x = "Prevalence in Negative Controls",
         y = "Prevalence in True Samples",
         title = "Prevalence Comparison") +
    theme_minimal()

ggsave("prevalence_comparison.pdf", width = 8, height = 7)

五、联合方法

5.1 两种方法联合使用

# === 联合频率法和流行度法 ===
contamdf_combined <- isContaminant(
    ps,
    method = "combined",           # 联合两种方法
    conc = "DNA_concentration",    # DNA浓度
    neg = "is_neg",                # 阴性对照标记
    threshold = 0.1                # 阈值
)

table(contamdf_combined$contaminant)  # 查看结果
cat("联合方法识别的污染物数:", sum(contamdf_combined$contaminant), "\n")

# 比较三种方法的结果
cat("\n=== 方法比较 ===\n")
cat("频率法:", sum(contamdf_freq$contaminant), "个\n")
cat("流行度法:", sum(contamdf_prev$contaminant), "个\n")
cat("联合法:", sum(contamdf_combined$contaminant), "个\n")

5.2 去除污染物并保存

# === 从数据中去除污染物 ===
# 选择使用哪种方法的结果(推荐联合法或根据数据情况选择)
contaminants <- contamdf_combined$contaminant  # 污染物标记

# 去除污染物
ps_clean <- prune_taxa(!contaminants, ps)  # 保留非污染物

# 同时去除阴性对照样本
ps_clean <- prune_samples(
    sample_data(ps_clean)$is_neg == FALSE,  # 只保留真实样本
    ps_clean
)

cat("清理前: ", ntaxa(ps), "个特征,", nsamples(ps), "个样本\n")
cat("清理后: ", ntaxa(ps_clean), "个特征,", nsamples(ps_clean), "个样本\n")

# 保存清理后的数据
saveRDS(ps_clean, "phyloseq_decontaminated.rds")

# === 查看被去除的污染物是什么 ===
contam_taxa <- tax_table(ps)[contaminants, ]  # 污染物的分类信息
cat("\n=== 被去除的污染物 ===\n")
print(as.data.frame(contam_taxa))

六、常见污染微生物参考

# === 已知的常见试剂污染物 ===
# 参考:Salter et al., BMC Biology 2014

known_contaminants <- c(
    # 常见试剂污染属
    "Bradyrhizobium",      # DNA提取试剂盒常见
    "Ralstonia",           # 水和试剂中常见
    "Methylobacterium",    # 实验室环境常见
    "Sphingomonas",        # 水和试剂中常见
    "Pseudomonas",         # 无处不在的环境菌(部分是污染)
    "Acinetobacter",       # 皮肤和环境
    "Stenotrophomonas",    # 水系统
    "Herbaspirillum",      # DNA提取试剂盒
    "Burkholderia",        # 试剂和环境
    "Propionibacterium",   # 皮肤(现更名Cutibacterium)
    "Corynebacterium"      # 皮肤
)

# 检查数据中是否存在已知污染物
if (!is.null(tax_table(ps))) {
    genus_col <- "Genus"  # 属级分类列名
    taxa_df <- as.data.frame(tax_table(ps))
    found_contaminants <- taxa_df[taxa_df[[genus_col]] %in% known_contaminants, ]
    cat("数据中发现的已知污染属:\n")
    print(unique(found_contaminants[[genus_col]]))
}

七、micRoclean MAG去污染

# === micRoclean:宏基因组MAG去污染(2025年新工具)===
pip install microclean  # 安装micRoclean

# micRoclean检测MAG(Metagenome-Assembled Genome)中的污染contig
# 适用于宏基因组binning后的质量控制

# 基本用法
microclean \
    --input mag_bins/ \            # MAG bin目录
    --output cleaned_bins/ \       # 清理后的输出
    --threads 16 \                 # 16线程
    --min-completeness 50 \        # 最低完整性50%
    --max-contamination 5          # 最高污染度5%

# micRoclean使用机器学习方法:
# 基于tetranucleotide频率、GC含量、覆盖度等特征
# 识别每个contig是否属于该MAG
# 去除与MAG主体不一致的污染contig

八、最佳实践流程

# === 完整的去污染最佳实践 ===

# 1. 实验设计阶段
#    - 每批次至少包含2-3个阴性对照(空白提取)
#    - 记录每个样本的DNA浓度(Qubit测量)
#    - 阳性对照(mock community)验证流程正确性

# 2. 数据分析阶段
# Step 1: 数据导入和初步质控
ps <- readRDS("raw_phyloseq.rds")  # 读取原始数据

# Step 2: 检查阴性对照
neg_reads <- sample_sums(ps)[sample_data(ps)$is_neg == TRUE]
cat("阴性对照reads:\n")
print(neg_reads)  # 应远低于真实样本

# Step 3: 选择去污染方法
# 有DNA浓度 → 频率法或联合法
# 只有阴性对照 → 流行度法
# 两者都有 → 联合法(推荐)

# Step 4: 运行decontam
contamdf <- isContaminant(ps, method = "combined",
                          conc = "DNA_concentration",
                          neg = "is_neg",
                          threshold = 0.1)

# Step 5: 检查结果合理性
# 查看被标记的是否包含已知污染物
# 确认没有误伤重要的生物学信号

# Step 6: 去除污染物
ps_clean <- prune_taxa(!contamdf$contaminant, ps)
ps_clean <- prune_samples(sample_data(ps_clean)$is_neg == FALSE, ps_clean)

# Step 7: 在方法部分报告去污染步骤
cat("\n=== 报告内容 ===\n")
cat("去污染方法: decontam (combined method)\n")
cat("阈值: 0.1\n")
cat("去除污染ASV数:", sum(contamdf$contaminant), "\n")
cat("保留ASV数:", ntaxa(ps_clean), "\n")

九、常见报错与解决

报错信息原因解决方案
No concentration data元数据中没有DNA浓度列添加DNA浓度数据或改用流行度法
No negative controls没有标记阴性对照在元数据中添加is_neg列
All taxa are contaminants阈值太宽松降低阈值(如0.05)
No contaminants found阈值太严格或确实没污染提高阈值(如0.5)或检查数据
Negative control has 0 reads阴性对照没有reads可能测序深度不够或确实没污染
phyloseq object error数据格式不匹配检查OTU表、分类表、元数据的行列对应

十、面试高频题

Q1:微生物组数据为什么需要去污染?

答: DNA提取试剂、PCR试剂、实验室环境中都含有微量微生物DNA。对于高生物量样本(如粪便),这些污染被淹没在大量目标DNA中影响很小。但对于低生物量样本(如血液、CSF、皮肤、空气),污染DNA可能占据大部分甚至全部检测到的微生物信号。经典例子:Salter等人2014年发现仅DNA提取试剂盒就贡献了数十个假阳性菌属。不去污染会导致:(1) 假阳性——报告不存在的微生物;(2) 丰度偏差——真实微生物的相对丰度被稀释;(3) 研究结论错误——在"无菌"部位发现的微生物可能全是污染。

Q2:decontam的频率法和流行度法分别适用于什么场景?

答: 频率法需要DNA浓度数据——原理是污染物来自固定量的试剂,所以在高浓度样本中被稀释、频率低,在低浓度样本中被"放大"、频率高。适合:有精确DNA浓度测量(Qubit)的实验。流行度法需要阴性对照——原理是污染物在阴性对照中比在真实样本中出现得更频繁。适合:有足够阴性对照(每批次≥2个)的实验。如果两者都有,用联合法最可靠。注意:频率法对DNA浓度变异小的样本效果差;流行度法对阴性对照数量太少时不可靠。

Q3:如何判断decontam的阈值设多少合适?

答: 默认阈值0.1是个合理的起点,但应该根据数据特征调整:(1) 画频率-浓度图看趋势是否合理——被标记的ASV是否确实呈现负相关趋势;(2) 检查被标记的是否包含已知污染物(如Bradyrhizobium、Ralstonia)——如果已知污染物没被标记,阈值可能太严格;(3) 检查是否误伤了生物学上重要的微生物——如果目标微生物被标记,阈值可能太宽松;(4) 用不同阈值(0.05、0.1、0.2、0.5)做敏感性分析,看核心结论是否稳定。

Q4:除了decontam,还有哪些去污染策略?

答: (1) 实验层面——最有效的方法是从源头减少污染:使用经过DNA去除处理的试剂、在超净工作台操作、设置多个阴性对照;(2) 简单过滤——去除在阴性对照中出现的所有ASV(粗暴但有效);(3) 比例过滤——去除在阴性对照中丰度>在样本中丰度X%的ASV;(4) SourceTracker——用贝叶斯方法估计每个样本中污染源的贡献比例;(5) micRoclean(2025年新工具)——专门针对MAG的contig级去污染,用机器学习方法。最佳实践是多种方法结合:实验控制+统计去污染+结果敏感性分析。


参考资料:decontam: Davis et al., Microbiome 2018 | Salter et al., BMC Biology 2014 | Karstens et al., mSystems 2019 | micRoclean: 2025 | 实验室污染综述: Eisenhofer et al., Trends Microbiol 2019