群体遗传学分析(选择信号 / 群体结构 / Fst / PCA / ADMIXTURE)¶
一句话概述¶
群体遗传学通过分析等位基因频率的时空分布来推断群体历史、自然选择和遗传结构,本教程覆盖PCA、ADMIXTURE群体结构分析、Fst分化检测和选择信号扫描的完整实战流程。
目录¶
1. 核心知识点¶
| 序号 | 步骤 | 工具 | 目的 | 输入 | 输出 | 关键参数 |
|---|---|---|---|---|---|---|
| 1 | 数据准备与质控 | PLINK2/VCFtools | 过滤低质量变异和样本 | VCF/PLINK格式 | 质控后数据集 | --maf 0.05 --geno 0.1 |
| 2 | LD修剪 | PLINK2 | 去除连锁位点 | 质控后数据 | 独立SNP子集 | --indep-pairwise 50 10 0.1 |
| 3 | PCA分析 | PLINK2/smartpca | 可视化群体遗传结构 | LD修剪后数据 | PC坐标 | PC数目 |
| 4 | ADMIXTURE分析 | ADMIXTURE | 推断祖先成分比例 | LD修剪后PLINK格式 | Q矩阵(祖先比例) | K值选择(CV error) |
| 5 | 系统发育树 | SNPhylo/RAxML | 群体间进化关系 | SNP数据 | Newick树文件 | bootstrap次数 |
| 6 | Fst群体分化 | VCFtools/PopGenome | 量化群体间遗传分化 | 分群后VCF | Fst值(全基因组/窗口) | 窗口大小 |
| 7 | 核苷酸多态性π | VCFtools/PopGenome | 衡量群体内遗传多样性 | 分群后VCF | π值(窗口) | 窗口大小/步长 |
| 8 | Tajima's D | VCFtools | 检测偏离中性模型 | VCF | D统计量(窗口) | 窗口大小 |
| 9 | 选择性扫描检测 | rehh/selscan | 检测正选择信号 | VCF + 遗传图谱 | iHS/XP-EHH分数 | EHH衰减阈值 |
| 10 | 群体历史推断 | SMC++/PSMC | 推断有效群体大小变化 | VCF/全基因组数据 | Ne~t曲线 | 突变率/世代时间 |
2. 各步骤详解¶
步骤1:数据准备与质控¶
白话解释:群体遗传学分析对数据质量非常敏感。低质量的SNP(如高缺失率、偏离HWE)和样本(如近亲、混血个体)会扭曲群体结构分析结果。严格的质控是第一步。
技术细节:
群体遗传学特有的质控考量: - MAF过滤:群体遗传学通常使用MAF≥5%(比GWAS更严格),因为稀有变异对PCA和ADMIXTURE的贡献有限且容易受到基因分型误差影响 - 缺失率:按群体分别检查,确保某一群体中的高缺失SNP不被保留 - HWE:不要对所有群体联合检验HWE(群体分层会导致偏离),应在每个群体内分别检验 - 亲缘关系:去除近亲后才能进行PCA和ADMIXTURE - LD filtering:对于PCA和ADMIXTURE,需要LD修剪后的独立位点
# 基本质控
plink2 --vcf all_populations.vcf.gz \
--maf 0.05 \
--geno 0.1 \
--mind 0.1 \
--hwe 1e-6 \
--max-alleles 2 \
--make-bed \
--out popgen_qc
# 计算样本间亲缘关系
plink2 --bfile popgen_qc \
--king-cutoff 0.0884 \
--out king_results
# 去除近亲
plink2 --bfile popgen_qc \
--remove king_results.king.cutoff.out.id \
--make-bed \
--out popgen_unrelated
echo "质控后SNP数: $(wc -l < popgen_unrelated.bim)"
echo "质控后样本数: $(wc -l < popgen_unrelated.fam)"
步骤2:LD修剪¶
白话解释:PCA和ADMIXTURE假设输入的SNP之间是相互独立的。如果不去除高LD的SNP,某些基因组区域(如MHC区域)会对结果产生过大的影响。LD修剪保留一组近似独立的SNP子集。
技术细节:
群体遗传学的LD修剪参数通常比GWAS更严格: - r² < 0.1(比GWAS常用的0.2更严格) - 这确保了SNP之间的独立性,使PCA和ADMIXTURE结果更可靠
还需要排除长程LD区域: - MHC区域(人类chr6:25-35Mb) - 染色体倒位区域(如人类chr8倒位) - 这些区域的高LD会形成PCA上的"假结构"
对于ADMIXTURE,LD修剪的严格程度直接影响CV error的最小值和K值的选择。过于宽松的修剪会高估K值。
# 严格LD修剪(r²<0.1)
plink2 --bfile popgen_unrelated \
--indep-pairwise 50 10 0.1 \
--out ld_prune
# 排除长程LD区域
cat > long_range_ld_hg38.txt << 'EOF'
6 25000000 35000000 MHC
8 7000000 13000000 INV
EOF
plink2 --bfile popgen_unrelated \
--extract ld_prune.prune.in \
--exclude range long_range_ld_hg38.txt \
--make-bed \
--out popgen_pruned
echo "LD修剪后SNP数: $(wc -l < popgen_pruned.bim)"
步骤3:PCA分析¶
白话解释:PCA(主成分分析)将高维基因型数据投影到二维或三维空间中,让我们直观看到不同群体之间的遗传距离和聚类关系。相近的点代表遗传相似的个体。
技术细节:
PCA在群体遗传学中的用途: - 识别遗传聚类(群体/亚群体) - 检测混血个体(位于两个群体之间) - 发现异常值(样本标签错误、种群混杂) - 为后续分析选择样本子集
PC的解读: - PC1通常反映最大的遗传分化方向 - 前2-3个PC往往能捕捉主要的群体结构 - 解释方差比例(eigenvalue)帮助判断群体结构的层次
注意事项: - 样本量不平衡会影响PCA:大群体的内部变异可能主导前几个PC - "projection PCA"可以将小样本量群体投影到大参考面板定义的PC空间中
# PLINK2 PCA
plink2 --bfile popgen_pruned \
--pca 20 \
--out pca_results
# smartPCA(更多统计选项)
# 准备par文件
cat > smartpca.par << 'EOF'
genotypename: popgen_pruned.bed
snpname: popgen_pruned.bim
indivname: popgen_pruned.fam
evecoutname: smartpca.evec
evaloutname: smartpca.eval
numoutevec: 20
numthreads: 16
EOF
smartpca -p smartpca.par
# R可视化PCA
library(ggplot2)
library(ggrepel)
# 读取PCA结果
pca <- read.table("pca_results.eigenvec", header=FALSE)
eigenval <- read.table("pca_results.eigenval", header=FALSE)
# 添加群体信息
pop_info <- read.table("population_labels.txt", header=TRUE)
pca_df <- merge(pca, pop_info, by.x="V2", by.y="IID")
# 计算方差解释比例
pct_var <- eigenval$V1 / sum(eigenval$V1) * 100
# 绘制PCA
ggplot(pca_df, aes(x=V3, y=V4, color=Population)) +
geom_point(size=2, alpha=0.7) +
labs(
x = paste0("PC1 (", round(pct_var[1], 1), "%)"),
y = paste0("PC2 (", round(pct_var[2], 1), "%)"),
title = "Population Structure (PCA)"
) +
theme_minimal(base_size=14) +
scale_color_brewer(palette="Set2")
ggsave("pca_plot.pdf", width=9, height=7)
步骤4:ADMIXTURE分析¶
白话解释:ADMIXTURE估计每个个体基因组中来自不同祖先群体的比例。比如一个个体可能是60%祖先A + 30%祖先B + 10%祖先C。通过尝试不同的K值(假设的祖先群体数),找到最能解释数据的群体数目。
技术细节:
ADMIXTURE使用最大似然方法估计: - Q矩阵:每个个体的祖先成分比例(N个体 × K个祖先) - F矩阵:每个祖先群体中每个SNP的等位基因频率
K值选择: - 对每个K值(如2-10)运行交叉验证(--cv) - 选择CV error最低的K值作为最优K - 但最优K不一定是唯一"正确"的K——不同K提供不同层次的群体结构信息
运行注意事项: - ADMIXTURE对初始值敏感,建议每个K运行多次(不同随机种子),选择最优结果 - 输入数据必须经过严格LD修剪 - 样本量不平衡会影响结果(过采样的群体可能被拆分为多个组分)
# 对K=2到K=10运行ADMIXTURE
for K in $(seq 2 10); do
admixture --cv popgen_pruned.bed ${K} -j16 --seed=42 \
| tee admixture_K${K}.log
done
# 提取CV error
grep "CV error" admixture_K*.log | \
awk '{print NR+1, $NF}' > cv_errors.txt
# 可视化CV error选择最优K
# ADMIXTURE结果可视化
library(ggplot2)
library(tidyr)
library(dplyr)
# 读取最优K的Q矩阵(假设K=4最优)
K <- 4
q_matrix <- read.table(paste0("popgen_pruned.", K, ".Q"))
fam <- read.table("popgen_pruned.fam")
pop_info <- read.table("population_labels.txt", header=TRUE)
# 整理数据
q_df <- cbind(IID=fam$V2, q_matrix)
q_df <- merge(q_df, pop_info, by="IID")
colnames(q_df)[2:(K+1)] <- paste0("Ancestry_", 1:K)
# 转为长格式
q_long <- q_df %>%
pivot_longer(cols=starts_with("Ancestry_"),
names_to="Ancestry", values_to="Proportion") %>%
arrange(Population, Ancestry)
# 结构图
ggplot(q_long, aes(x=IID, y=Proportion, fill=Ancestry)) +
geom_bar(stat="identity", width=1) +
facet_grid(~Population, scales="free_x", space="free_x") +
scale_fill_brewer(palette="Set2") +
labs(y="Ancestry Proportion", title=paste0("ADMIXTURE K=", K)) +
theme_minimal() +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
panel.spacing = unit(0.1, "lines")
)
ggsave("admixture_barplot.pdf", width=12, height=4)
# CV error图
cv <- read.table("cv_errors.txt")
ggplot(cv, aes(x=V1, y=V2)) +
geom_line() + geom_point() +
labs(x="K", y="Cross-validation error", title="ADMIXTURE CV Error") +
scale_x_continuous(breaks=2:10) +
theme_minimal()
步骤5:系统发育树¶
白话解释:用SNP数据构建群体之间的进化关系树,直观展示哪些群体亲缘关系更近。可以构建个体水平的树或群体水平的NJ树/ML树。
技术细节:
SNP数据构建系统发育树的方法: - 距离法(NJ树):计算个体/群体间的遗传距离矩阵,用邻接法建树。快速但可能丢失信息。 - 最大似然法(RAxML/IQ-TREE):更准确但计算量大,适合SNP concatenation数据 - SNPhylo:专为全基因组SNP数据设计的流水线,自动做LD修剪和建树
注意:SNP系统发育树假设所有位点独立进化且无重组,这对于连锁的基因组数据是近似。对于群体水平推断,网状进化(admixture graph, TreeMix)可能比严格的树形更合适。
# SNPhylo流水线
snphylo.sh -v filtered.vcf \
-l 0.1 \
-m 0.1 \
-M 0.05 \
-b 1000 \
-t 16
# 或手动方式:PLINK距离矩阵 → NJ树
plink2 --bfile popgen_pruned \
--distance square 1-ibs \
--out dist_matrix
# 用R构建NJ树
library(ape)
library(ggtree)
# 读取距离矩阵
dist_mat <- read.table("dist_matrix.dist", header=FALSE, skip=1)
ids <- read.table("dist_matrix.dist.id")
rownames(dist_mat) <- ids$V2
colnames(dist_mat) <- ids$V2
# NJ树
nj_tree <- nj(as.dist(dist_mat))
nj_tree <- root(nj_tree, outgroup="outgroup_sample", resolve.root=TRUE)
# 可视化
ggtree(nj_tree, layout="rectangular") +
geom_tiplab(size=2) +
theme_tree2()
步骤6:Fst群体分化¶
白话解释:Fst(固定指数)量化两个群体之间的遗传分化程度。Fst=0表示完全没有分化(随机交配),Fst=1表示完全固定(两群体没有共享等位基因)。全基因组滑窗Fst可以找到高度分化的区域(可能受到定向选择)。
技术细节:
Fst的计算方法: - Weir & Cockerham (1984):最广泛使用,考虑了样本量偏差 - Hudson估计:对小样本量更鲁棒 - Reynolds距离:适合近缘群体
全基因组Fst分析策略: - 全局Fst:整体群体分化程度 - 逐位点Fst:每个SNP的分化值 - 滑窗Fst:常用10-100kb窗口,5-50kb步长 - 离群值检测:寻找Fst显著高于基因组平均水平的区域
注意:Fst受样本量、MAF和遗传漂变的影响。小群体即使没有选择也可能有高Fst区域(漂变效应)。
# VCFtools计算全局Fst
vcftools --vcf filtered.vcf \
--weir-fst-pop population_A.txt \
--weir-fst-pop population_B.txt \
--out fst_A_vs_B
# 滑窗Fst
vcftools --vcf filtered.vcf \
--weir-fst-pop population_A.txt \
--weir-fst-pop population_B.txt \
--fst-window-size 50000 \
--fst-window-step 25000 \
--out fst_windowed_A_vs_B
# 多群体Fst(PLINK2)
plink2 --bfile popgen_qc \
--fst POP \
--pheno population_assignment.txt \
--out pairwise_fst
步骤7:核苷酸多态性π¶
白话解释:π(nucleotide diversity)衡量一个群体内的遗传多样性——随机取两条序列,它们在一个位点上不同的概率有多大?π高说明群体多样性高;某个区域π特别低可能意味着那里经历了选择性清除。
技术细节:
π的计算:对所有SNP位点,计算每对个体之间的碱基差异数,除以可比较的位点总数。
应用: - 全基因组π:比较不同群体的遗传多样性水平 - 滑窗π:检测局部多样性变化(低π谷可能是选择清除信号) - π比值(πA/πB):两群体多样性比较,偏离1.0的区域可能受到差异选择
与Tajima's D结合: - 低π + 负Tajima's D → 近期选择性清除(正选择) - 高π + 正Tajima's D → 平衡选择
# 计算滑窗π
vcftools --vcf pop_A.vcf \
--window-pi 50000 \
--window-pi-step 25000 \
--out pi_pop_A
vcftools --vcf pop_B.vcf \
--window-pi 50000 \
--window-pi-step 25000 \
--out pi_pop_B
步骤8:Tajima's D¶
白话解释:Tajima's D检验一个区域的等位基因频率谱是否偏离中性进化的期望。中性条件下D≈0;正选择(选择性清除)使D<0;平衡选择使D>0。
技术细节:
Tajima's D的原理: - 比较两种多态性估计:θ_π(基于配对差异)和θ_W(基于分离位点数) - 中性条件下两者相等(D=0) - 选择性清除后:大量低频变异(多分离位点,少配对差异),D<0 - 平衡选择:中频变异增多,D>0 - 群体瓶颈也会导致D<0(需要区分)
显著性判断: - |D| > 2 通常被认为偏离中性 - 但需要考虑人口统计学历史的影响(如瓶颈、扩张) - 建议与中性模拟比较,或使用基因组分布的离群值
步骤9:选择性扫描检测¶
白话解释:当正选择驱动一个有利突变快速增频时,它会"拖着"周围的变异一起增频(搭便车效应),形成一个长的低多样性区域。iHS和XP-EHH通过检测异常长的单倍型来发现这些信号。
技术细节:
iHS(integrated Haplotype Score): - 比较一个SNP两个等位基因的EHH(Extended Haplotype Homozygosity)衰减速率 - 如果一个等位基因的EHH衰减很慢(单倍型很长),说明它可能最近才被选择增频 - 适合检测不完全选择性清除(选择仍在进行中)
XP-EHH(Cross-Population Extended Haplotype Homozygosity): - 比较两个群体中同一位点的EHH - 适合检测一个群体中已经完成的选择性清除(等位基因已固定) - 能检测到iHS遗漏的古老的完全清除
nSL:iHS的改进版本,对重组率变异更鲁棒。
输入要求: - 分相的单倍型数据(phased haplotypes) - 遗传图谱(genetic map,将物理距离转换为遗传距离)
# 使用selscan计算iHS
selscan --ihs \
--vcf pop_A_phased.vcf.gz \
--map genetic_map.map \
--out ihs_pop_A \
--threads 16
# 标准化iHS
norm --ihs --files ihs_pop_A.ihs.out --bins 100
# 计算XP-EHH
selscan --xpehh \
--vcf pop_A_phased.vcf.gz \
--vcf-ref pop_B_phased.vcf.gz \
--map genetic_map.map \
--out xpehh_A_vs_B \
--threads 16
norm --xpehh --files xpehh_A_vs_B.xpehh.out --bins 100
步骤10:群体历史推断¶
白话解释:有效群体大小(Ne)反映了一个群体在进化历史中的规模变化。通过分析基因组中的变异模式,可以反推出过去数万到数百万年间群体大小如何变化——如扩张、瓶颈、分裂等事件。
技术细节:
PSMC(Pairwise Sequentially Markovian Coalescent): - 适用于单个个体的高覆盖度全基因组数据(≥20×) - 分析基因组上异合子位点的分布模式 - 推断10万-数千万年前的Ne变化 - 分辨率在近期(<1万年)较差
SMC++: - 可使用多个未分相的全基因组序列 - 整合了样本频率谱(SFS)信息 - 对近期历史(<1000代)有更好的分辨率 - 不需要分相数据
MSMC2: - 需要分相的单倍型数据 - 可推断多群体的分离时间 - 对2-8个单倍型效果最佳
# PSMC分析流程
# 1. 生成diploid consensus序列
samtools mpileup -C50 -uf ref.fa sample.bam | \
bcftools call -c | \
vcfutils.pl vcf2fq -d 10 -D 100 | \
gzip > diploid.fq.gz
# 2. 创建PSMC输入
fq2psmcfa -q20 diploid.fq.gz > diploid.psmcfa
# 3. 运行PSMC
psmc -N25 -t15 -r5 -p "4+25*2+4+6" -o output.psmc diploid.psmcfa
# 4. Bootstrap(100次)
seq 100 | xargs -I {} -P 16 \
psmc -N25 -t15 -r5 -b -p "4+25*2+4+6" \
-o round-{}.psmc diploid.psmcfa
# 5. 绘图(需要指定突变率和世代时间)
psmc_plot.pl -u 1.4e-08 -g 25 -p output output.psmc
# SMC++分析
# 1. 转换VCF为SMC格式
smc++ vcf2smc filtered.vcf.gz smc_data/chr1.smc.gz chr1 Pop1:sample1,sample2,sample3
# 2. 估计群体历史
smc++ estimate -o smc_output/ 1.4e-8 smc_data/*.smc.gz
# 3. 绘图
smc++ plot smc_plot.pdf smc_output/model.final.json
3. 实战命令/代码(完整流程)¶
#!/bin/bash
# ====================================================
# 群体遗传学分析完整流程
# ====================================================
set -euo pipefail
THREADS=16
VCF="all_populations.vcf.gz"
POP_FILE="population_info.txt" # IID Population
OUTDIR="popgen_results"
mkdir -p ${OUTDIR}/{qc,pca,admixture,fst,selection,history}
# ---- Step 1-2: 质控+LD修剪 ----
echo "=== 数据质控 ==="
plink2 --vcf ${VCF} --maf 0.05 --geno 0.1 --mind 0.1 --hwe 1e-6 \
--max-alleles 2 --make-bed --out ${OUTDIR}/qc/popgen_qc
plink2 --bfile ${OUTDIR}/qc/popgen_qc --king-cutoff 0.0884 --out ${OUTDIR}/qc/king
plink2 --bfile ${OUTDIR}/qc/popgen_qc \
--remove ${OUTDIR}/qc/king.king.cutoff.out.id \
--make-bed --out ${OUTDIR}/qc/popgen_unrel
plink2 --bfile ${OUTDIR}/qc/popgen_unrel --indep-pairwise 50 10 0.1 --out ${OUTDIR}/qc/ld
plink2 --bfile ${OUTDIR}/qc/popgen_unrel \
--extract ${OUTDIR}/qc/ld.prune.in \
--make-bed --out ${OUTDIR}/qc/popgen_pruned
echo "QC后: $(wc -l < ${OUTDIR}/qc/popgen_unrel.bim) SNPs, $(wc -l < ${OUTDIR}/qc/popgen_unrel.fam) samples"
echo "LD修剪后: $(wc -l < ${OUTDIR}/qc/popgen_pruned.bim) 独立SNPs"
# ---- Step 3: PCA ----
echo "=== PCA ==="
plink2 --bfile ${OUTDIR}/qc/popgen_pruned --pca 20 --out ${OUTDIR}/pca/pca
# ---- Step 4: ADMIXTURE ----
echo "=== ADMIXTURE ==="
for K in $(seq 2 8); do
admixture --cv ${OUTDIR}/qc/popgen_pruned.bed ${K} -j${THREADS} --seed=42 2>&1 \
| tee ${OUTDIR}/admixture/log_K${K}.txt
mv popgen_pruned.${K}.Q ${OUTDIR}/admixture/
mv popgen_pruned.${K}.P ${OUTDIR}/admixture/
done
grep "CV error" ${OUTDIR}/admixture/log_K*.txt > ${OUTDIR}/admixture/cv_summary.txt
# ---- Step 5: Fst ----
echo "=== Fst ==="
# 提取各群体样本列表
awk '$2=="PopA" {print $1}' ${POP_FILE} > ${OUTDIR}/fst/pop_A.txt
awk '$2=="PopB" {print $1}' ${POP_FILE} > ${OUTDIR}/fst/pop_B.txt
vcftools --gzvcf ${VCF} \
--weir-fst-pop ${OUTDIR}/fst/pop_A.txt \
--weir-fst-pop ${OUTDIR}/fst/pop_B.txt \
--fst-window-size 50000 --fst-window-step 25000 \
--out ${OUTDIR}/fst/fst_A_vs_B
# ---- Step 6: π和Tajima's D ----
echo "=== π和Tajima's D ==="
vcftools --gzvcf ${VCF} --keep ${OUTDIR}/fst/pop_A.txt \
--window-pi 50000 --window-pi-step 25000 \
--out ${OUTDIR}/selection/pi_A
vcftools --gzvcf ${VCF} --keep ${OUTDIR}/fst/pop_A.txt \
--TajimaD 50000 \
--out ${OUTDIR}/selection/tajD_A
# ---- Step 7: iHS ----
echo "=== 选择性扫描 ==="
selscan --ihs --vcf pop_A_phased.vcf.gz \
--map genetic_map.map --out ${OUTDIR}/selection/ihs_A --threads ${THREADS}
norm --ihs --files ${OUTDIR}/selection/ihs_A.ihs.out --bins 100
echo "=== 分析完成 ==="
4. 面试常问点¶
Q1:什么是Fst?如何解读不同的Fst值?
Fst(固定指数)衡量群体间遗传分化程度,代表总遗传变异中由群体间差异贡献的比例。Fst=0:无分化(一个随机交配群体);Fst=0.05-0.15:中等分化;Fst=0.15-0.25:显著分化;Fst>0.25:高度分化。例如人类大陆间Fst约0.12,狗品种间Fst约0.3。全基因组高Fst窗口可能指示定向选择区域。
Q2:PCA和ADMIXTURE分析有什么区别和联系?
PCA是无参数方法,将遗传变异投影到低维空间,不假设群体数目。ADMIXTURE是模型化方法,假设K个祖先群体,估计每个体的祖先比例。联系:两者都揭示群体结构,结果通常一致——PCA中处于两群体之间的个体在ADMIXTURE中显示混合祖先。区别:PCA更适合数据探索和异常值检测;ADMIXTURE提供定量的祖先比例估计,但需要选择K值。
Q3:如何检测正选择?不同方法各适用什么场景?
常用方法:(1)基于群体分化:Fst离群值(比较群体间分化的极端区域);(2)基于频率谱:Tajima's D<0,过量低频等位基因;(3)基于单倍型:iHS(进行中的选择)、XP-EHH(完成的选择);(4)基于多样性:低π区域。适用场景:Fst适合比较两个群体受到不同选择压力的区域;iHS/XP-EHH适合近期选择(<30,000年);Tajima's D对选择清除敏感但也受人口统计学影响。
Q4:ADMIXTURE的K值如何选择?最优K一定是"真实"的祖先群体数吗?
K值选择主要通过交叉验证(CV error):对每个K计算CV error,选择最低值对应的K。但最优K不一定代表"真实"的祖先群体数,原因:(1)群体结构是连续的,离散K是近似;(2)CV error差异可能很小,多个K同样合理;(3)样本量和SNP数影响K选择。建议展示多个K的结果,结合生物学背景解读。
Q5:为什么群体遗传学分析前需要LD修剪?
PCA和ADMIXTURE假设SNP间独立。高LD区域(如MHC)如果不修剪,会在PCA中形成虚假的聚类轴,在ADMIXTURE中高估K值。LD修剪确保每个SNP提供独立的遗传信息,使结果反映真实的群体结构而非基因组局部特征。注意:Fst和选择信号分析通常不需要LD修剪(需要保留局部LD信息)。
Q6:PSMC和SMC++各有什么优缺点?
PSMC:只需1个高覆盖度个体,推断范围10^4-10^7年,但近期分辨率差、需要≥20×覆盖度。SMC++:可使用多个低覆盖度样本,近期分辨率好(<1000代),不需要分相,但需要更多计算资源。选择建议:如果只有一个高覆盖度基因组用PSMC;如果有多个样本且关心近期历史用SMC++。
5. 易错/易混淆点¶
PCA/ADMIXTURE前忘记LD修剪:未修剪的数据会让PCA被高LD区域(如MHC)主导,ADMIXTURE会高估K值。这是最常见的新手错误。
混淆样本量不平衡对PCA的影响:如果一个群体有100个样本,另一个只有10个,PCA前几个PC可能主要反映大群体的内部变异。可以通过下采样或使用projection解决。
将Fst离群值直接等同于选择:高Fst可能由遗传漂变(小群体)、瓶颈效应或背景选择导致,不一定是定向选择。需要结合多种证据(π、Tajima's D、iHS)综合判断。
iHS/XP-EHH使用未分相数据:基于单倍型的选择检测方法需要高质量的分相(phasing)。使用未分相或质量差的分相数据会严重影响结果准确性。
PSMC的突变率和世代时间设置错误:PSMC的时间轴缩放完全依赖于突变率(μ)和世代时间(g)的假设。不同假设会给出完全不同的时间范围。务必明确说明使用的参数。
对小群体过度解读选择信号:有效群体大小很小的群体(如岛屿种群),遗传漂变的影响很强,很多看似"选择"的信号可能只是漂变。需要中性模拟来建立null分布。
忽略批次效应对群体结构的影响:如果不同群体在不同批次基因分型,技术差异可能被误判为群体结构。应在质控阶段检查批次与群体的混杂关系。
6. 补充知识¶
经典群体遗传学指标¶
- θ_W(Watterson's theta):基于分离位点数估计的群体突变率
- θ_π(核苷酸多样性π):基于配对差异估计的突变率
- Tajima's D:θ_π - θ_W的标准化值
- Fu's Fs:检测群体扩张的另一统计量
- Dxy:群体间绝对分歧度
推荐软件和资源¶
- PLINK2: https://www.cog-genomics.org/plink/2.0/
- ADMIXTURE: https://dalexander.github.io/admixture/
- selscan: https://github.com/szpiech/selscan
- SMC++: https://github.com/popgenmethods/smcpp
- PSMC: https://github.com/lh3/psmc
- PopGenome (R): 一站式R包
- scikit-allel (Python): Python群体遗传学工具库
推荐学习资源¶
- Gillespie (2004) "Population Genetics: A Concise Guide" — 入门教材
- Nielsen & Slatkin (2013) "An Introduction to Population Genetics" — 经典教材
- 1000 Genomes Project数据 — 练习数据集
- Graham Coop群体遗传学笔记 — 优秀免费资源