4、输入文件格式:VCF格式与转换归纳总结

4.1 为什么非得是VCF?

你想想看,做变异检测的,不管是WGS、WES还是靶向测序,最后交出来的报告,十有八九都是VCF格式。VCF全称是Variant Call Format,说白了,它就是变异检测领域的“通用语言”。

我个人习惯,拿到一个VCF文件,第一件事不是急着跑ANNOVAR,而是先看一眼它的元数据部分,也就是以“#”开头的行。这就好比读一本书,先翻翻目录和前言,心里大概有个底。

核心要点: ANNOVAR原生不接受原始的VCF文件。你必须先把它转换成ANNOVAR自己的“avinput”格式,或者利用ANNOVAR自带的convert2annovar.pl脚本做一步式转换。

4.2 VCF文件的结构长什么样?

一个标准的VCF文件,结构很清晰。我把它拆成三部分来讲:

  • 元数据行: 以 ## 开头,描述文件格式、版本、样本信息、过滤条件等。这部分是给程序看的,也是给有经验的人看的。
  • 标题行: 只有一行,以 #CHROM 开头,定义了后面数据列的标题。
  • 数据行: 每一行代表一个变异位点的信息,各列由制表符(Tab)分隔。

一个典型的数据行有8个核心列,再加上样本列。核心8列如下:

列号 名称 说明
1 CHROM 染色体名称,例如 chr1 或 1
2 POS 变异在染色体上的起点位置(1-based)
3 ID dbSNP的rs号,如果没有则为 .
4 REF 参考等位基因
5 ALT 替代等位基因。如果是SNP,就是单碱基;如果是Indel,可能是 ATG 这样的序列。
6 QUAL 变异质量值。Phred-scale质量得分,值越高,变异越可信。
7 FILTER 过滤状态。PASS表示通过所有过滤,否则是具体的过滤标签。
8 INFO 额外的变异信息,用键值对表示,例如 DP=100;AF=0.5

我自己在项目中经常遇到一个问题:染色体前缀。有的VCF用 chr1,有的用 1。ANNOVAR默认识别不带“chr”前缀的染色体名。所以你在转换前,需要确认这一点。如果你的VCF里是 chr1,我建议你用sed或awk先把“chr”去掉。

为什么会这样?因为ANNOVAR内部的参考基因组文件(如hg19、hg38)的染色体名字,默认是不带“chr”的。

4.3 INFO字段的解析,这里有个坑

VCF文件的INFO列,内容丰富,但也是“重灾区”。最常见的几个INFO条目如下:

  • DP:测序深度,在这个位点上覆盖到的reads总数。
  • AF:等位基因频率,ALT等位基因在样本中的频率。
  • AC:ALT等位基因的计数。
  • AN:总的等位基因数。
  • MQ:Mapping Quality的均值。

我个人习惯,在INFO列里,特别关注 DP 和 AF 这两个值。特别是当你做过滤的时候,比如你要丢掉深度低于20x的位点,在转换成avinput之前,最好提前处理掉,否则ANNOVAR不会帮你做这件事。

请注意: ANNOVAR的 convert2annovar.pl 脚本,默认是“无脑”读取VCF的CHROM、POS、REF、ALT列,然后生成avinput。它不会替你处理INFO里的过滤条件。所以,先过滤,再转换,这是个好习惯。

我遇到过最头疼的事情是什么?

曾经有一个合作者给我的VCF,居然在同一行里,ALT列用逗号隔开了多个等位基因,比如 A,G。这种多等位基因位点,ANNOVAR处理起来会出错,因为它的格式默认每一行只记录一个变异等位基因对。

4.4 转换工具:一招鲜,吃遍天?

把VCF转换成ANNOVAR能吃的avinput格式,主要有两种方式。我最常用的是第一种。

方法一:使用 convert2annovar.pl(推荐)

这是ANNOVAR自带的小工具,用法很简单:

perl convert2annovar.pl -format vcf4 example.vcf > example.avinput

-format vcf4 告诉它输入格式是VCF 4.x版本。这个命令会帮你完成格式转换,同时丢掉一些ANNOVAR不关心的列。

如果你想保留样本的基因型信息(比如用于后续的过滤),可以加上 -includeinfo 参数:

perl convert2annovar.pl -format vcf4 -includeinfo example.vcf > example_withinfo.avinput

方法二:手动编写脚本(自己动手,丰衣足食)

有时候,VCF文件太大,或者包含一些特殊的信息,你需要自己写一个脚本来完成转换。其实,avinput的格式很简单:它是制表符分隔的文本文件,每行包含6个列:

chr pos ref alt (funcref) (exonref)
  • chr:染色体名
  • pos:起始位置
  • ref:参考等位基因
  • alt:替代等位基因
  • funcref:通常是空格,保留给注释器使用
  • exonref:同上,保留用

手动转换的思路,就是从VCF的CHROM、POS、REF、ALT列分别取出来,然后按制表符拼接。我写过最简短的awk脚本:

awk 'BEGIN{OFS="\t"} !/^#/ {print $1, $2, $4, $5, ".", "."}' example.vcf > example.avinput

这个脚本跳过所有注释行(以#开头的行),然后提取第1、2、4、5列,最后补两列“.”。

4.5 文件转换流程图

下面这张图,总结了我上面讲的核心流程。从VCF原始文件开始,经过一次简单的格式转换,最终成为ANNOVAR能够理解的输入。

VCF 转 ANNOVAR 输入流程图 原始 VCF 文件 格式检查:染色体前缀、多等位基因 convert2annovar.pl 推荐:自动处理格式 awk / Python 脚本 手动:灵活但需小心 avinput 格式文件 注意: 先过滤低质量位点
一个小技巧: 如果你的VCF文件特别大(比如有10G),我建议你不要用 convert2annovar.pl,而是用管道的方式,一边解压,一边转换,一边注释。比如:
zcat huge.vcf.gz | perl convert2annovar.pl -format vcf4 -includeinfo - > huge.avinput
这个“-”告诉程序从标准输入读取。这样能节省大量磁盘IO和临时空间。

4.6 常见问题:我的VCF为什么转不了?

我把自己踩过的坑,总结成了一张表,你对照着看,能省不少时间。

问题 现象 解决方法
染色体名不统一 转换后avinput中的 chr1 导致后续注释找不到位置 用 sed 's/^chr//' 去除“chr”前缀
多等位基因位点 ALT列为 A,G,转换后变成一行,但ANNOVAR只认一对一的变异 使用 bcftools norm -m -any 将其拆分成单等位基因
染色体顺序错误 avinput中染色体顺序乱了,导致后期合并结果混乱 按照染色体自然顺序排序,可以用 sort -k1,1 -k2,2n
参考基因组版本不匹配 注释结果全部为NA 确认VCF是hg19还是hg38,并下载对应版本的ANNOVAR数据库

4.7 总结:记住这几个关键点

  • VCF格式是标准输入,但不能直接喂给ANNOVAR。
  • 转换的核心是提取 CHROM, POS, REF, ALT 四列。
  • convert2annovar.pl 是官方推荐的转换工具。
  • 转换前,一定要做过滤和格式清洗。
  • 遇到多等位基因,先用 bcftools norm 或 vt decompose 拆分。

我以前有一次,因为没注意染色体前缀的问题,导致整个批次的样本注释结果全错了,白白浪费了三天时间。所以你想想看,花5分钟检查一下VCF文件,能把后面可能出的问题扼杀在摇篮里。