This is a test version of Biostars. For the public version, visit https://www.biostars.org.
Count the number of homozygous and heterozygous variants in VCF file

I would like to find the count of homozygous major(0|0),homozygous minor(1|1) and heterozygous(1|0,0|1) alleles for each position of a chromosome.I would like to form a table like this:

POS 00 1 0/0 1 11

Pos1 n1 n2 n3

Pos2 n4 n5 n6

where n1...n6 are the counts .

See the example file here 1000Genomes

Any suggestions to try to get this information would be much appreciated

Thanks in Advance

1000genomes awk count allele

2 answers

An awk solution:

$ zcat input.vcf.gz|awk -v OFS="\t" '$0 !~ "^#" {hom_ref = 0; hom_alt = 0; het = 0; for(i=10;i<=NF;i++) { if($i ~ /0\|0/) hom_ref++; else if($i ~ /1\|1/) hom_alt++;  else het++; } print $1, $2, hom_ref, hom_alt, het}'

fin swimmer

Why do you think so?

I get the the count of 0|0 right. But when i manually calculated it gives me the wrong count for 0|1,1|0 and 1|1

Could you please post a small example of your file and the output you get and which you would expect?

Sure. Here is the example :

Position, Count_0|0, Count_0|1, Count_1|0 ,Count_1|1

16050115, 404, 0 , 0 , 0

16050213, 403, 0 , 1 , 0

16050607 400 , 2 , 2 , 0

#CHROM    POS     ID      REF     ALT     QUAL    FILTER  INFO    FORMAT  HG00096 HG00097 HG00099 HG00100 HG00101 HG00102 HG00103 HG00105 
22      16050115        .       G       A       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     
22      16050213        .       C       T       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     
22      16050607        .       G       A       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     
22      16050739        .       TA      T       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     
22      16050783        .       A       G       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     
22      16050840        .       C       G       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     
22      16050847        .       T       C       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     
22      16050922        rs367963583     T       G       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0    0|0
22      16050984        rs188945759     C       G       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0
22      16051075        .       G       A       .       PASS    .       GT      0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0     0|0
22      16051249        rs62224609      T       C       .       PASS    .       GT      0|0     1|0     1|0     0|0     0|0     1|0     0|0     0|0
22      16051453        rs143503259     A       C,G     .       PASS    .       GT      0|0     1|0     0|0     0|0     0|0     1|0     0|0    0|0

OK, thanks. Mistake found. There was in elsemissing here: if($i ~ /1\|1/) hom_alt++;. It must be else if. I corrected it in my answer.

fin swimmer

I get the count of home_ref and alt right. The problem with het is I want to only sum the ones with 0|1 and 1|0. but it gives me the sum of 0|1,1|0,0|2,etc.. I am sorry I havent mentioned it before .How do i proceed ? I am new to linux

That wasn't clear to me, that you want to differ the heterozygous. You just have to modify my code in that way, that you define a new variable for each genotype you like to count, check with in if-statement if it exist, count and output all the variables.

So for checking the genotype 0|1 and 1|0 it looks like this:

$ zcat input.vcf.gz|awk -v OFS="\t" '$0 !~ "^#" {hom_ref = 0; hom_alt = 0; het_01 = 0; het_10=0; for(i=10;i<=NF;i++) { if($i ~ /0\|0/) hom_ref++; else if($i ~ /1\|1/) hom_alt++;  else if($i ~ /0\|1/) het_01++; else if($i ~ /1\|0/) het_10++; } print $1, $2, hom_ref, hom_alt, het_01, het_10}'

Why do want to make a difference between 0|1 and 1|0?

fin swimmer

@finswimmer,I dont want to make the difference , but want to exclude 0|2,0|3 etc and keep only count(1|0 and 0|1) for heterozygous.

cat vcffile \
| perl -ane '
/^#/ and next;
%c = ();
foreach (@F[9..$#F]) { /^([^:]+)/ and $c{$1}++ }
print "$F[0]\t$F[1]";
foreach $gt (sort keys %c) { print "\t$gt:$c{$gt}" }
print "\n"

I found this code gives me the right count

I added code markup to your post for increased readability. You can do this by selecting the text and clicking the 101010 button. When you compose or edit a post that button is in your toolbar, see image below:

101010 Button

Log in to answer this question.