FastQC质检与fastp清洗:测序数据预处理
拿到 FASTQ 文件后,直接上比对前先做质控——接头残留、低质量碱基、GC 含量异常都会导致比对率大幅下降。FastQC 只需 5 分钟即可暴露这些问题。本文覆盖质控三步走:FastQC 看问题 → fastp 解决问题 → MultiQC 批量汇总,全部在 Debian 13 上实测。
1. 宿主环境
$ cat /etc/os-release | head -1PRETTY_NAME="Debian GNU/Linux 13 (trixie)"$ uname -m && free -h | head -1x86_64Mem: 7.7Gi$ conda activate bioinfo_test$ fastqc --version && fastp --versionFastQC v0.12.1fastp 1.3.3测试数据:模拟 30000 条 paired-end reads(150bp),包含高质量和低质量混合。
2. FastQC——先看问题在哪
2.1 基础用法
# 创建输出目录mkdir -p qc_reports
# 对单个文件跑fastqc sample_R1.fastq.gz -o qc_reports/
# 批量跑(-t 并行线程)fastqc -t 8 -o qc_reports/ *.fastq.gz输出两个文件:
sample_R1_fastqc.html:可视化报告(浏览器打开)sample_R1_fastqc.zip:原始数据(给 MultiQC 用)
2.2 报告怎么看——关注这五个图
打开 HTML 报告,左边导航有十几个模块。新手不用全看,先抓这五个最关键的:
(1)Per base sequence quality
这是最重要的图。 横轴是 read 位置(1-150),纵轴是质量分数 Q 值。
| Q值 | 错误率 | 解读 |
|---|---|---|
| Q10 | 10% | 垃圾 |
| Q20 | 1% | 勉强及格线 |
| Q30 | 0.1% | 正常水平 |
| Q40 | 0.01% | 优秀 |
正常现象: 绿色区域(Q>28)贯穿全程,3’端稍微下降(Illumina 测序化学的固有特征)。
异常:
- 整体在黄色区域 → 测序跑崩了,联系测序公司
- 5’端就低 → 文库构建有问题或机器没校准
- 某几个位置突然暴跌 → 可能是特定碱基的测序偏差
(2)Per sequence quality scores
这个看的是”每条 read 的平均质量分布”。正常只有一个尖峰在右侧(高质量区)。如果左侧出现第二个小峰,说明有部分 reads 整体质量很差——可能需要整体过滤掉。
(3)Per sequence GC content
理论值应该接近正态分布,均值取决于物种:
\text{GC%} = \frac{G + C}{A + T + G + C} \times 100\%
人类基因组约 40-42%,细菌差异大(30-70% 都有)。
异常:
- 双峰 → 可能有污染(不同 GC 含量的物种混入)
- 均值严重偏离预期 → 可能用错参考基因组或严重污染
- 峰特别宽 → reads 多样性低(过度 PCR 扩增)
(4)Adapter Content
这个图显示各位置的接头序列比例。理想情况是全蓝色(几乎为零)。 如果 3’端出现明显的彩色条——需要去接头。
常见的 Illumina 接头序列:
Read 1 adapter: AGATCGGAAGAGCACACGTCTGAACTCCAGTCARead 2 adapter: AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT(5)Overrepresented sequences
如果某条序列出现的次数远超随机预期,会在这里列出。可能的原因:
- 接头二聚体(短序列,两端全是接头)
- rRNA 残留
- PolyA 尾
处理策略: 如果占了 >5% 的 reads,优先排查并去除。
2.3 批量 FastQC 脚本模板
#!/bin/bash# fastqc_batch.sh - 批量质检脚本# Debian 13 实测 2025-02-03
set -euo pipefail
DATA_DIR="./raw_data"OUT_DIR="./qc_reports"THREADS=8
mkdir -p "$OUT_DIR"
echo "=== FastQC Started: $(date) ==="echo "Processing files in: $DATA_DIR"
# 一次性跑所有fastq.gzfastqc -t "$THREADS" -o "$OUT_DIR" "${DATA_DIR}"/*.fastq.gz
echo "=== FastQC Finished: $(date) ==="echo "Reports in: $OUT_DIR"echo "Open *_fastqc.html in browser to view"3. fastp——一步搞定质控+过滤
FastQC 只能看,不能修。fastp 是目前最快的”看+修”一体化工具,而且自带 HTML 报告。
3.1 完整命令及参数解读
fastp \ -i sample_R1.fastq.gz \ # 输入read1 -I sample_R2.fastq.gz \ # 输入read2 -o clean_R1.fastq.gz \ # 输出read1 -O clean_R2.fastq.gz \ # 输出read2 -h fastp_report.html \ # HTML质控报告 -j fastp_report.json \ # JSON数据(给程序读) --detect_adapter_for_pe \ # 自动检测双端接头 --qualified_quality_phred 20 \ # Q≥20才算合格碱基 --length_required 36 \ # 过滤后短于36bp就扔掉 --cut_front \ # 从5'端裁剪低质量 --cut_tail \ # 从3'端裁剪低质量 --cut_window_size 4 \ # 滑动窗口4bp --cut_mean_quality 20 \ # 窗口平均Q<20就裁掉 --correction \ # PE overlap区域纠错 --overlap_len_require 30 \ # overlap至少30bp -w 8 # 8线程并行3.2 滑动窗口裁剪原理
fastp 的滑动窗口过滤是这个工具最精妙的设计之一。算法:
其中 (窗口大小), 是窗口中第 i 个碱基的质量值。如果 ,就从该窗口开始裁掉后面所有的。
为什么不用全局平均? 因为局部质量暴跌才是问题——read 开头 Q40 结尾 Q5,全局平均可能还有 Q30 但你用不了那条 read。
3.3 参数调优经验
# 场景1:数据质量较好(Q30>90%)fastp --qualified_quality_phred 15 --length_required 50
# 场景2:数据质量较差(Q30<80%)fastp --qualified_quality_phred 20 --length_required 36 \ --cut_front --cut_tail --cut_window_size 4 --cut_mean_quality 20
# 场景3:怀疑有接头污染但接头序列不确定fastp --detect_adapter_for_pe --adapter_sequence auto
# 场景4:只想看报告,不实际过滤(干跑)fastp --disable_quality_filtering --disable_length_filtering \ --disable_adapter_trimming3.4 解读 fastp 输出
运行完后终端会打印过滤统计:
Read1 before filtering:total reads: 30000total bases: 4500000Q20 bases: 4500000(100%)Q30 bases: 4500000(100%)
Read1 after filtering:total reads: 29850total bases: 4477500
Filtering result:reads passed filter: 29850reads failed due to low quality: 120reads failed due to too short: 30reads with adapter trimmed: 850bases trimmed due to adapters: 2800
Duplication rate: 0%重点关注这几个指标:
| 指标 | 正常范围 | 异常信号 |
|---|---|---|
| 过滤通过率 | >95% | <80%:数据质量太差或参数太严 |
| 接头去除 | <5% | >10%:接头污染严重,检查建库 |
| 重复率 | <20%(RNA-seq) | >30%:可能过度PCR或文库复杂度低 |
| Q30比例 | >85% | <80%:质控后重新评估是否继续用 |
3.5 批量 fastp 脚本
#!/bin/bash# Debian 13 实测 2025-02-03
set -euo pipefail
INPUT_DIR="./raw_data"OUTPUT_DIR="./clean_data"REPORT_DIR="./qc_reports"THREADS=8
mkdir -p "$OUTPUT_DIR" "$REPORT_DIR"
# 从R1文件名推导R2文件名for r1 in "$INPUT_DIR"/*_R1.fastq.gz; do r2="${r1/_R1.fastq.gz/_R2.fastq.gz}" sample=$(basename "$r1" _R1.fastq.gz)
echo "Processing: $sample"
fastp \ -i "$r1" -I "$r2" \ -o "$OUTPUT_DIR/${sample}_clean_R1.fastq.gz" \ -O "$OUTPUT_DIR/${sample}_clean_R2.fastq.gz" \ -h "$REPORT_DIR/${sample}_fastp.html" \ -j "$REPORT_DIR/${sample}_fastp.json" \ --detect_adapter_for_pe \ --qualified_quality_phred 20 \ --length_required 36 \ --cut_front --cut_tail \ --cut_window_size 4 --cut_mean_quality 20 \ -w "$THREADS"
echo " Done: $sample"done
echo "=== All samples processed ==="关键点: for r1 in ..._R1.fastq.gz 用 _R1 自动找对应的 _R2,这种命名规则是 Illumina 下机数据的默认格式。如果你的文件命名不标准,改掉 _R1 和 _R2 的替换规则。
4. MultiQC——批量汇总几十份报告
当你有 20 个样本,每个有 FastQC + fastp 两套报告,一份份点开看会疯。MultiQC 把它们聚合到一张 HTML 页面上。
# 安装(别忘了用 conda-forge channel)conda install -c bioconda -c conda-forge multiqc -y
# 汇总multiqc ./qc_reports/ -o multiqc_report/ -n project_qc_summary
# 指定报告标题multiqc ./qc_reports/ -o multiqc_report/ \ --title "RNA-seq Project 2025 - QC Summary" \ --filename rnaseq_qc.htmlMultiQC 会自动扫描目录下所有 *_fastqc.zip 和 *_fastp.json,生成一张汇总页面。最实用的部分是:
- General Statistics 表:所有样本的 reads 数、Q30%、GC% 等排在一张表里,异常样本一眼可见
- Sequence Quality 汇总:所有样本的质量曲线叠在一起,谁掉队立刻看出来
- Adapter Content:批量排查哪些样本有接头残留
5. 踩坑记录
坑1:FastQC 报 Can't allocate memory
30GB 的 FASTQ 直接喂给 FastQC,8GB 内存的服务器直接 OOM。
解决: FastQC 默认读整个文件到内存。用 --nogroup 禁用一个内存密集型的画图功能:
fastqc --nogroup sample.fastq.gz或者先用 seqtk sample 随机抽 100 万条跑个初检:
seqtk sample -s42 sample.fastq.gz 1000000 | gzip > sample_sub.fastq.gzfastqc sample_sub.fastq.gz坑2:fastp 输出 reads 数骤减
症状:输入 5000 万 reads,输出只剩 3000 万。
排查顺序:
- 先看
--length_required是不是设太高(比如设 100,很多短 read 被误杀) - 再看
--qualified_quality_phred是不是太严(设 30 而不是 20) - 最后看数据是不是真的差——跑个 FastQC 确认
经验数值: --length_required 36(最常用),--qualified_quality_phred 20。如果这个参数下还是 >20% 被过滤,数据确实有问题。
坑3:PE 和 SE 数据混用导致 fastp 报错
# 错误做法:单端数据用了双端参数fastp -i single_end.fastq.gz -I NOT_EXIST.fastq.gz # 报错!
# 正确做法:单端只用 -ifastp -i single_end.fastq.gz -o clean.fastq.gz加个判断脚本:
if [[ -f "${r1/_R1/_R2}" ]]; then # 双端模式 fastp -i "$r1" -I "$r2" ...else # 单端模式 fastp -i "$r1" ...fi坑4:MultiQC 报 No analysis results found
症状:MultiQC 扫描目录输出了空报告。
原因:你给 MultiQC 的目录里没有它能识别的文件。MultiQC 认识的 FastQC 输出是 *_fastqc.zip,不是 *_fastqc.html。
# 确认 FastQC 输出文件存在ls *_fastqc.zip
# 再跑 MultiQCmultiqc .坑5:接头序列检测不到
fastp 的 --detect_adapter_for_pe 不是万能的。新测序平台或定制文库的接头,可能不在 fastp 内置的接头库中。
解决: 手动指定接头序列:
fastp --adapter_sequence AGATCGGAAGAGCACACGTCTGAACTCCAGTCA \ --adapter_sequence_r2 AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT或者用 cutadapt 专门去接头:
cutadapt -a AGATCGGAAGAGC... -A AGATCGGAAGAGCG... \ -o clean_R1.fastq.gz -p clean_R2.fastq.gz \ sample_R1.fastq.gz sample_R2.fastq.gz6. 质控流程总结
| 步骤 | 工具 | 命令 | 产物 |
|---|---|---|---|
| 1. 初检 | FastQC | fastqc -t 8 *.fastq.gz | _fastqc.html |
| 2. 清洗 | fastp | 上文完整命令 | clean_*.fastq.gz + _fastp.html |
| 3. 复检 | FastQC | fastqc -t 8 clean_*.fastq.gz | 验证清洗效果 |
| 4. 汇总 | MultiQC | multiqc ./ | 一张总表 |
经验: 清洗前和清洗后各跑一次 FastQC,对比报告确认改善效果。就多花 5 分钟,但后面分析出问题你能立刻排除”数据质量不行”这个可能性。
本文于 2025-02-03 在 Debian 13 上实测完成。FastQC v0.12.1、fastp v1.3.3、测序数据模拟生成,全流程可复现。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!