第2章 VCF格式详解

VCF,全称Variant Call Format,是生物信息学里最通用的变异存储格式。记得我刚入行时,被这个格式的字段数量吓了一跳——不就是记录一个变异位点吗?怎么列了那么多东西?后来才明白,每个字段背后都藏着一段实验历史和计算逻辑。

今天我们就把它拆开揉碎,从文件结构到场位含义,一路讲清楚。

2.1 VCF文件整体结构

一个标准的VCF文件,你可以想象成三块积木堆叠:元信息头、列标题行、数据行。缺一不可。

先看一个完整的VCF文件头(我通常用 grep -v "^##" 快速跳过注释去看数据):

##fileformat=VCFv4.2
##fileDate=20240101
##source=GATK4
##contig=<ID=chr1,length=248956422>
##INFO=<ID=DP,Number=1,Type=Integer,Description="Total Depth">
##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
#CHROM  POS  ID  REF  ALT  QUAL  FILTER  INFO  FORMAT  SAMPLE1  SAMPLE2
chr1  12345  .  A  G  500.90  PASS  DP=100  GT:GQ  0/1:99  1/1:99

结构清楚吗?我们来逐个拆解。

关键点:所有以 ## 开头的行都是元信息头,# 开头的只有一行——那是列标题。数据行没有 # 前缀。

2.2 元信息头(Meta-information Lines)

元信息头以 ## 开头,每行一个键值对或结构体。它的作用类似“数据字典”:告诉下游工具每个字段的含义和类型。

常见的元信息头包括:

  • ##fileformat —— VCF规范版本,我现在用VCFv4.2,有些旧数据集是4.1或4.0。
  • ##INFO —— 描述INFO列里的字段。
  • ##FORMAT —— 描述FORMAT列里的字段。
  • ##FILTER —— 自定义过滤标签。
  • ##contig —— 参考基因组染色体信息。

举个例子,我们想定义一个自定义INFO字段:

##INFO=<ID=AF,Number=A,Type=Float,Description="Allele Frequency for each alt allele">

这里 Number=A 表示该字段值的数量会随ALT等位基因个数变化。我曾在项目中因为Number写错,导致下游bcftools query解析时报错,浪费了半天才排查出来。这个坑,各位一定要记住。

再看FORMAT定义:

##FORMAT=<ID=AD,Number=R,Type=Integer,Description="Allelic depths for each allele">

Number=R代表每个参考等位基因+每个ALT等位基因各一个值。这些元信息行不是摆设,bcftools、PLINK等工具全靠它们来解析字段。

2.3 列标题与数据行字段详解

列标题行固定9个必填列,后面跟着一个或多个样本列。这9列是:CHROM, POS, ID, REF, ALT, QUAL, FILTER, INFO, FORMAT。我们逐一说清楚。

列名含义典型值课堂提醒
CHROM染色体/contig名称chr1, chrX, chrM必须与参考基因组一致
POS在染色体上的位置(1-based)12345很多工具默认用0-based,注意转换
IDdbSNP的rs编号或自定义IDrs12345 或 .点号表示无ID
REF参考等位基因序列A, AT, CTG必须是参考基因组上真实序列
ALT替代等位基因序列,可多个G, T, CT, <DEL>多个ALT用逗号分隔
QUALPhred质量评分500.90值越高表示变异可信度越高
FILTER过滤状态PASS, q20, LowQualPASS表示通过所有过滤器
INFO变异的附加信息,键值对DP=100;AF=0.45多个键值对用分号分隔
FORMAT样本基因型字段名称列表GT:GQ:AD冒号分隔的字段名

我曾经踩过的坑:在同一份数据里,我把CHROM列写成了“chr1”但参考基因组用“1”开头,结果bcftools merge死活合并不了。CHROM命名必须和参考FASTA的contig名完全一致,大小写都不能错。

2.4 样本列与FORMAT字段

从第10列开始,每一列对应一个样本。第一个样本列的值必须与FORMAT列定义的顺序对应——用冒号分隔。

最常见的FORMAT字段包括:

  • GT(Genotype):0/0表示纯合参考,0/1表示杂合,1/1表示纯合变异。注意相位用|,非相位用/。
  • GQ(Genotype Quality):Phred质量的二重评分。
  • DP(Read Depth):覆盖该位点的总读数。
  • AD(Allelic Depth):每个等位基因的读数列表。

来看一个具体的样本列:

FORMAT  SAMPLE1
GT:AD:DP:GQ  0/1:10,8:18:99

这表示样本SAMPLE1的基因型为杂合(0/1),参考等位基因深度10,ALT深度8,总深度18,GQ为99(非常可靠)。

我在做药物靶点关联分析时,经常需要把GT字段转化为“0,1,2”的剂量编码,这里有一个小技巧:

bcftools +dosage -o output.vcf input.vcf

不过要注意,如果样本列有丢失数据(用 . 表示),必须先过滤掉。

2.5 INFO字段详解(药物靶点关联常用)

INFO列里可以塞很多信息,在药物基因组学中,我们关注几个关键标签:

INFO标签含义药物靶点场景
DP总深度低深度可能引起假阳性
AF等位基因频率稀有变异(AF<0.01)可能影响药物代谢
AN总等位基因数用于计算缺失率
ACALT等位基因计数结合AF判断变异丰度

比如要快速提取所有AF大于0.05且深度超过30的位点:

bcftools view -i 'INFO/DP > 30 & INFO/AF > 0.05' input.vcf

这个命令我几乎每天都会用到,很顺手。

2.6 一张图看懂VCF结构

下面这张SVG图把VCF的骨架和关键字段整理在了一起,方便你对照回忆:

VCF文件结构总览 ## 元信息头 / Meta-information Lines 定义文件格式、INFO/FORMAT/FILTER字段、参考基因组版本等 #CHROM POS ID REF ALT QUAL FILTER INFO FORMAT [样本1] [样本2] ... 数据行 (每行一个变异位点) chr1 12345 . A G 500.90 PASS DP=100;AF=0.3 GT:GQ 0/1:99 1/1:99 chr1 67890 rs123 T C 1200.00 PASS DP=200;AF=0.5 GT:GQ 0/0:99 0/1:99 样本列 / FORMAT字段 GT=基因型, GQ=基因型质量, DP=深度, AD=等位基因深度 注意 • 每个数据行都必须有9个固定列 • INFO字段通过##INFO预先定义 • FORMAT与样本列顺序对应 • 缺失值用 . 表示 9+2 结构 固定9列 + 至少1个样本列 样本列数无上限

个人习惯:我拿到一个陌生的VCF文件,第一件事就是跑 bcftools head -n 20 | less 看元信息头,确认FORMAT和INFO字段的定义,否则很容易把GT和AD理解反。

2.7 实战小技巧:快速验证VCF格式

检测VCF是否规范,我常用的三个命令:

  1. 检查行数统计:bcftools stats input.vcf
  2. 查看所有样本名:bcftools query -l input.vcf
  3. 提取特定字段:bcftools query -f '%CHROM\t%POS\t%REF\t%ALT[\t%GT]\n' input.vcf

你看,其实掌握VCF格式没那么难。把9个固定列和样本列之间的关系理清,后面做知识图谱关联时,你就能准确地从VCF里提取药物靶点相关的变异了。

嗯,VCF格式我们就讲到这里。它的每一个字段都像基因组的“指纹印”,读懂了,你就能跟数据对话了。