第4章 FILTER和INFO字段:过滤标志与变异位点属性

VCF文件里除了基因型,还有两列信息特别关键——FILTER和INFO。

说白了,FILTER告诉你这个位点“能不能用”,INFO告诉你这个位点“具体怎么样”。

我刚开始做变异检测时,经常把这两个字段混在一起。后来被坑了几次才发现:分清它们,是做好注释分析的起点。

核心一句话:

  • FILTER → 质检结果(通过/不通过/未检测)
  • INFO → 位点属性(频率、深度、质量指标等)
FILTER与INFO字段核心关系图 FILTER 与 INFO 字段:过滤标志 vs 变异属性 VCF 变异位点 FILTER(过滤标志) INFO(变异属性) PASS (通过) 特定过滤值 AC/AF/AN SOR/QD/FS FILTER决定位点是否可信,INFO提供位点详细特征——两者在注释与过滤栈中缺一不可

4.1 FILTER字段:PASS与非PASS

FILTER字段位于VCF文件的第7列。它记录的是:这个变异位点是否通过了质量过滤。

快速理解:

  • PASS → 位点通过了所有预设过滤条件,可以放心使用
  • . → 未进行任何过滤,这意味着状态不明,需要谨慎
  • 具体名称 → 如 QD<2.0、FS>60,表示触发了某个过滤规则

为什么会这样?

举个例子。你想想看,一个位点虽然被检测出来,但测序深度只有1X,或者链偏好性极强,这样的位点你敢信吗?

GATK VQSR或硬过滤后,FILTER字段会写清楚这个位点“有没有问题”。我个人习惯是先看一眼FILTER的分布情况,再决定怎么往下走。

避坑提醒:

我曾经在一个项目里,看到的FILTER值全是“.”,以为是所有位点都通过了。后来才发现,是上游没跑过滤步骤。结果整个关联分析都是基于未过滤的数据做的……那感觉,你懂的。

记住:. ≠ PASS。. 表示“没检测”,PASS 才表示“没问题”。

4.1.1 常见FILTER标志速查

FILTER值 含义 处理建议
PASS 通过所有过滤 放心使用
. 未进行过滤 建议自行过滤后再用
VQSRTrancheSNP99.90to100.00 VQSR分箱过滤 低质量区域,慎用
SB 链偏向性过高 很可能是假阳性
LowQual 低质量(GATK默认标记) 建议直接排除

我建议你在做批次关联分析之前,先用bcftools或vcftools看一眼FILTER的分布:

# 统计FILTER字段各值的出现次数
bcftools query -f '%FILTER\n' your.vcf.gz | sort | uniq -c | sort -rn

# 保留PASS位点
bcftools view -f PASS your.vcf.gz -o pass_only.vcf.gz

嗯,这里要注意:bcftools view -f PASS 只保留FILTER为PASS的位点。如果你想保留PASS和.,就得用 -f .,PASS。我每次都会检查一下,不然容易漏。


4.2 INFO字段:变异位点的属性库

INFO字段是VCF的“属性大本营”。它用key=value的形式,记录了这个位点的各种特征。

说白了,INFO就是一堆预先计算好的注释指标。你用bcftools annotate加进去的dbSNP ID、千人基因组频率、CADD分值,全都会写进INFO字段。

INFO字段结构示例:

AC=123;AF=0.0246;AN=5000;DP=12500;FS=3.8;QD=28.1;SOR=0.54;MQRankSum=0.23

每个标签对应一个具体属性,分号分隔,键值对形式。

我在项目中遇到过好几次,有人把AF(等位基因频率)和MAF(最小等位基因频率)搞混。虽然大部分情况下AF就是MAF,但严格来说AF是ALT的等位基因频率,不是自动取最小值。使用时最好确认一下注释来源。

4.2.1 常用INFO标签分类

类目 常见标签 说明
频率统计 AC/AF/AN 等位基因计数、频率、总等位基因数
测序深度 DP 覆盖该位点的总reads数
质量度量 QD / FS / SOR / MQ QualByDepth / FisherStrand / StrandOddsRatio / RMSMappingQuality
功能注释 ANN / CSQ / ENSG 由SnpEff / VEP 等工具注释的功能信息
数据库交集 dbSNP / CLNSIG / CADD 与外部数据库交集的标识与风险评分

你想想看,一次批次分析动辄几十万甚至上百万位点,如果不把INFO标签搞清楚,后面根本没法做。

4.2.2 查看INFO字段定义

VCF文件头部(##INFO开头的行)会定义每个标签的类型和描述。我建议你先用grep抓出来看看:

# 查看所有INFO标签定义
bcftools head your.vcf.gz | grep "^##INFO"

# 只看某几个关键标签的详细定义
bcftools head your.vcf.gz | grep -E "^##INFO=

输出内容大致长这样:

##INFO=
##INFO=
##INFO=

个人技巧:我一般写分析脚本前,都会跑一遍这个命令,把INFO标签表先列出来。这样后面用bcftools query -f '%INFO/TAG'取数据时,不会写错标签名。

4.2.3 自定义INFO标签

你完全可以往INFO字段里加自己的计算结果。比如你自己算了一个群体分化指数FST,就可以用bcftools annotate加进去:

# 先准备一个带注释的文本文件(tabix索引过)
echo -e "#CHROM\tPOS\tID\tREF\tALT\tFST\n1\t1000\t.\tA\tG\t0.15" > my_anno.txt
bgzip my_anno.txt && tabix -s1 -b2 -e2 my_anno.txt.gz

# 把FST写入INFO字段
bcftools annotate -a my_anno.txt.gz -c CHROM,POS,ID,REF,ALT,-,FST -h my_header.txt input.vcf.gz -o output.vcf.gz

注意:自定义标签必须事先在VCF头部定义好格式(##INFO行)。我刚开始做的时候忘了加头部定义,直接报错,折腾了半天。


4.3 FILTER与INFO的联合使用

两者联合起来才是完整套路。我的常规流程是:

  1. 第一步:基于FILTER做硬过滤 → 先用PASS去掉低质量位点
  2. 第二步:基于INFO做软筛选 → 根据DP、QD、FS等指标进一步挑出高质量位点
  3. 第三步:提取INFO注释 → 用bcftools query或自定义脚本提取你需要的属性

举个例子,我要分析一批全外显子数据中的罕见致病突变,就会这样操作:

# 步骤1:只保留PASS位点
bcftools view -f PASS all_sites.vcf.gz -o pass_sites.vcf.gz

# 步骤2:按深度和质量进一步过滤
bcftools view -i 'DP>10 & QD>2.0 & FS<60.0' pass_sites.vcf.gz -o filtered.vcf.gz

# 步骤3:提取目标INFO标签
bcftools query -f '%CHROM\t%POS\t%REF\t%ALT\t%AF\t%ANN\n' filtered.vcf.gz > extracted_ann.txt

避坑经验:

我曾经在一个批次效应分析项目里,只做了FILTER过滤就跑去跑PCA了。结果发现有几个批次明显偏移,排查了三天才找到原因——INFO字段里的DP在批次间差异巨大。原来有两个批次用的是不同的测序平台,覆盖深度差异导致批次效应。

所以,FILTER解决的是“质量能不能用”,INFO解决的是“属性有什么影响”。批次关联分析里,两者必须同时关注。


4.4 实战:快速查看VCF中FILTER和INFO分布

我一般拿到一个新的VCF文件,会先跑下面这几行命令,快速摸清FILTER和INFO的情况:

# 1. 看FILTER分布
bcftools query -f '%FILTER\n' your.vcf.gz | sort | uniq -c | sort -rn

# 2. 看几条具体位点的FILTER和INFO
bcftools query -f '%CHROM\t%POS\t%FILTER\t%INFO/DP\t%INFO/AF\t%INFO/QD\n' your.vcf.gz | head -20

# 3. 检查INFO标签完整性(看有没有缺失值)
bcftools query -f '%INFO/DP\n' your.vcf.gz | grep -c '\.'

记住,良好的数据洞察力,是从每次拿到数据后先跑几个统计命令开始的。


本章要点总结:

  • FILTER → 位点过滤标志,PASS表示可信,非PASS或被.表示谨慎处理
  • INFO → 位点属性库,包含频率、深度、质量、功能注释等关键信息
  • 联合使用 → 先FILTER硬过滤,再INFO软筛选,最后提取目标属性
  • 自定义扩展 → INFO支持自定义标签,但需先定义头部
  • 批次分析必做 → 检查FILTER和INFO的分布,避免批次间系统偏差