基因型计数与等位基因计数归纳总结
说实话,做了这么多年群体遗传分析,我见过最多的问题就出在最基础的地方——基因型计数和等位基因计数搞混了。这两个概念是你做一切频率计算的地基。地基不稳,后面什么PCA、群体结构、选择信号分析全是白搭。今天咱们就把这块彻底捋清楚。
1. 先搞清楚这两个计数到底在数什么
基因型计数,数的是人。每个样本携带什么基因型,数一数每种基因型有多少个样本。比如一个SNP位点有AA、AT、TT三种基因型,你手上有100个样本,数出来AA是30个,AT是50个,TT是20个——这就是基因型计数。
等位基因计数,数的是拷贝。每个样本贡献两个等位基因拷贝(二倍体生物嘛),你数的是A这个碱基出现了多少次,T这个碱基出现了多少次。说白了,就是把基因型计数转换成等位基因层面的数量。
我刚开始带团队的时候,有个新人拿着数据跑过来问我:「老师,为什么我算的等位基因频率总和不是1?」我一看,他直接把基因型计数的比例当成了等位基因频率。嗯,这是最常见的入门坑。
2. 从基因型到等位基因,其实就是一道算术题
推导公式特别简单。你想想看,每个纯合子贡献2个相同的等位基因,每个杂合子贡献1个A和1个a。那么:
等位基因A的计数 = 纯合子AA的个体数 × 2 + 杂合子Aa的个体数 × 1
等位基因a的计数 = 纯合子aa的个体数 × 2 + 杂合子Aa的个体数 × 1
总等位基因数 = 样本总数 × 2(二倍体)。然后用A的计数除以总计数,就是A的频率。
举个例子。假设一个位点有200个样本:
| 基因型 | 计数(个体数) | 贡献A拷贝数 | 贡献a拷贝数 |
|---|---|---|---|
| AA | 60 | 60 × 2 = 120 | 0 |
| Aa | 80 | 80 × 1 = 80 | 80 × 1 = 80 |
| aa | 60 | 0 | 60 × 2 = 120 |
| 合计 | 200 | 200 | 200 |
等位基因A的频率 = 200 / (200+200) = 0.5。就这么简单。
3. 实战中数据长什么样?我拿真实项目示范一下
下面这段代码是我实际项目里提取计数信息的简化版。VCF文件解析后,基因型计数字段通常是GT:DP:GQ这种格式,我会先统计每个位点的基因型分布:
# 伪代码:从基因型计数推导等位基因计数
# 假设已从VCF解析出每个样本的基因型
genotype_counts = {"AA": 60, "Aa": 80, "aa": 60}
# 等位基因计数
A_count = genotype_counts["AA"] * 2 + genotype_counts["Aa"]
a_count = genotype_counts["aa"] * 2 + genotype_counts["Aa"]
total_alleles = A_count + a_count
A_freq = A_count / total_alleles
a_freq = a_count / total_alleles
print(f"A等位基因计数: {A_count}")
print(f"a等位基因计数: {a_count}")
print(f"A频率: {A_freq:.4f}")
print(f"a频率: {a_freq:.4f}")
输出结果:
A等位基因计数: 200
a等位基因计数: 200
A频率: 0.5000
a频率: 0.5000
你看,代码逻辑跟手算完全一致。我在项目里习惯把这个步骤写成独立函数,这样后面做批量位点分析时直接调用就行。
4. 等位基因计数与基因型计数的关系图谱
下面这张图把整个推导路径串了一遍。我每次培训新人的时候都会先画这张图,它能把两个计数的关系可视化出来,比纯文字好理解得多。
这张图从左到右看,就是标准分析流水线。我个人习惯在每个位点跑完统计后,先检查基因型计数之和是否等于样本总数,这是数据完整性的第一道防线。
5. 三个最容易翻车的地方
我见过太多次因为计数细节导致分析重来的案例了。下面这三个坑,你大概率也会遇到:
- 样本分型率低于阈值:如果一个位点只有60%的样本有基因型数据,剩下的全是缺失,你直接拿这60%做等位基因计数——偏倚会非常大。我曾经有个全基因组关联分析(GWAS)项目,就是因为没过滤低分型率位点,前20个显著信号全是假阳性。
- 杂合子计数翻倍漏算:有人写脚本的时候,只给纯合子乘以了2,杂合子忘了加。结果A计数和a计数都少了一半,频率倒是没变,但后面的群体遗传多样性指标全错了。
- 多等位基因位点的处理:大部分SNP是二态的,但偶尔会遇到三态甚至四态位点。这时候用上面的二态公式会漏掉部分等位基因。我的做法是先检测等位基因种类数,超过2种就走多等位基因通用计算分支。
6. 遇到大规模数据怎么办?
几十个样本手算没问题,但全基因组层面动辄几百万个位点、上万样本,这时候必须写脚本批量处理。给你看一个实际项目中的处理框架:
# 批量位点等位基因计数处理流程
for each variant in VCF:
# 步骤1:提取该位点的所有样本基因型
genotypes = extract_genotypes(variant)
# 步骤2:过滤缺失(通常是 ./., 0/0 也是有效)
valid_gts = [g for g in genotypes if g != "./."]
if len(valid_gts) / total_samples < min_call_rate:
mark_low_quality(variant)
continue
# 步骤3:基因型计数
counts = {"AA": 0, "Aa": 0, "aa": 0}
for gt in valid_gts:
if gt == "0/0": counts["AA"] += 1
elif gt == "0/1" or gt == "1/0": counts["Aa"] += 1
elif gt == "1/1": counts["aa"] += 1
# 步骤4:等位基因计数
A_count = counts["AA"] * 2 + counts["Aa"]
a_count = counts["aa"] * 2 + counts["Aa"]
# 步骤5:计算频率并写入输出
total = A_count + a_count
output[variant] = {
"A_freq": A_count / total,
"a_freq": a_count / total,
"n_alt": a_count,
"n_total": total
}
我在项目中一般会加一个质量控制(QC)模块,直接把这个流程跑完后生成一份质控报告,标注所有分型率低、等位基因计数异常的位点。你想想看,如果等位基因计数阶段就埋了雷,后面做群体结构分析时再排查,工作量会大很多。
7. 把这两个计数放进更完整的分析上下文
基因型计数和等位基因计数不只是两个数字。它们往下游走,会直接影响:
- 哈代-温伯格平衡检验:基于等位基因频率计算期望基因型数,再与实际基因型计数做卡方检验。
- 群体分化指数Fst:依赖每个亚群的等位基因频率。
- 选择信号分析(如iHS、XP-EHH):需要准确的等位基因频率作为输入。
- 多群体联合分析:每个群体独立做等位基因计数,再合并比较。
说白了,这两个计数就是整个群体遗传分析大厦的砖和瓦。我曾经在一个跨国合作项目中,因为某个位点在两个群体中的等位基因计数方向搞反了,导致Fst计算值异常,浪费了整整两周排查。从那以后,我每个位点都坚持输出计数中间结果做人工抽检。
基因型计数和等位基因计数,一个是数个体,一个是数拷贝。从个体数到拷贝数,中间只隔了一个「乘以2」的换算。但就是这一步,足够让粗心的人栽跟头。记住:先看分型率,再算计数,最后做交叉验证。把这套流程养成习惯,后面的大规模分析你才能放心往下推。