问题描述
FID IID FA MO SEX PHENO SNP1 SNP2 SNP3 SNP4
1 1 0 0 1 1 20 00 20 11
1 2 0 0 1 1 11 00 20 20
1 3 0 0 1 1 11 20 11 20
1 4 0 0 1 1 00 11 11 20
snp.txt文件:
1 SNP1 20 A G
1 SNP2 45 T C
1 SNP3 56 A G
1 SNP4 80 C G
我的输出文件应如下所示(在根据snp.txt中的第4列和第5列将数字从第7列转换为raw.txt中的字母之后):
FID IID FA MO SEX PHENO SNP1 SNP2 SNP3 SNP4
1 1 0 0 1 1 AA CC AA CG
1 2 0 0 1 1 AG CC AA CC
1 3 0 0 1 1 AG TT AG CC
1 4 0 0 1 1 GG TC AG CC
snp.txt文件的第2列是从第7列(raw.txt)开始的raw.txt文件的头。 snp.txt文件的第4和第5列代表第2列的snps的次要和主要等位基因。我希望将SNP1,SNP2,SNP3和SNP4下的列以0,1,2格式使用第4列转换为ACGT格式和5作为地图。
raw.txt的SNP1,SNP2,SNP3和SNP4列代表未成年人等位基因的0.1或2个副本(snp.txt文件的第4列)。第5列是主要的等位基因。如果如raw.txt中所示,SNP1是20,则有2个次要等位基因副本,根据snp.txt,它是A。因此20应该改为AA(20中的2是次要等位基因A的计数)。 SNP1 11表示存在1个次要等位基因副本。因此11应该是AG。 SNP1 00表示没有次要等位基因,只有主要等位基因。因此00应该是snp.txt文件的GG(第5列中的字母的2个副本)。
实际上,我有超过65,000个snps,这意味着raw.txt文件有很多列。我有下面的代码(我在stackoverflow上找到的代码我做了一些编辑:
awk 'NR==FNR {a[$2,20]=$4$4; a[$2,11]=$4$5; a[$2,"00"]=$5$5; next} $7~/^[0-2]/ {
$7=a["SNP1",$7]; $8=a["SNP2",$8];9=a["SNP3",$9];$10=a["SNP4",$10]}1'
snp.txt raw.txt > output.txt
如果raw.txt文件只有4个snps,这就是我想要的。当我有超过65,000个snps时,我不知道如何通过raw.txt的第7列中的字段进行此循环。我想要一个代码(最好是awk语言),该代码可以遍历raw.txt的许多列,以将00、11、20格式的snps更改为双等位字母格式。谢谢。
解决方法
您的awk
很好!这是针对可变数量的snps的方法。
> cat tst.awk
NR==FNR {
snp[$2 "20"] = $4 $4
snp[$2 "11"] = $4 $5
snp[$2 "00"] = $5 $5
next
}
FNR==1 { # read the columns/snps
for (i=7;i<=NF;i++) col[i] = $i
print
next
}
{
for (i=7;i<=NF;i++) $i = snp[col[i] $i]
print
}
用法:
> awk -f tst.awk snp.txt raw.txt
FID IID FA MO SEX PHENO SNP1 SNP2 SNP3 SNP4
1 1 0 0 1 1 AA CC AA CG
1 2 0 0 1 1 AG CC AA CC
1 3 0 0 1 1 AG TT AG CC
1 4 0 0 1 1 GG TC AG CC
修改之处在于,我们读取了标头并保存了snps,稍后再将它们用于映射。这两个动作都是通过典型的for
循环完成的,从我们想要的列到最后一列(NF
),剩下的就是您已经在做的事情,除了语法更清晰以外。