Search code examples
bashawkvcf-variant-call-format

Automated awk command to remove duplicated fields in a VCF's INFO column keeping the first occurrence


The presence of duplicated fields in my VCF files are causing a problem for other programs. A VCF file is a tab separated file. One cell of the INFO column is given below. The structure of the cell is:

info1=x;info2=y;.....;info1=.;info2=.;.....

I need a script to remove the duplicated fields repeated after first occurrence and replace the cell with:

info1=x;info2=y;.....

The actual cell...

.;ANNOVAR_DATE=2017-07-17;Func.refGene=exonic;Gene.refGene=GRIK3;GeneDetail.refGene=.;ExonicFunc.refGene=nonsynonymous_SNV;AAChange.refGene=GRIK3:NM_000831:exon10:c.C1348T:p.R450W;avsnp150=.;cosmic70=ID\x3dCOSM186835\x3bOCCURENCE\x3d2(large_intestine),1(lung),1(haematopoietic_and_lymphoid_tissue);ExAC_ALL=.;ExAC_AFR=.;ExAC_AMR=.;ExAC_EAS=.;ExAC_FIN=.;ExAC_NFE=.;ExAC_OTH=.;ExAC_SAS=.;SIFT_score=0.001;SIFT_pred=D;Polyphen2_HDIV_score=1.0;Polyphen2_HDIV_pred=D;Polyphen2_HVAR_score=0.916;Polyphen2_HVAR_pred=D;LRT_score=0.000;LRT_pred=D;MutationTaster_score=0.983;MutationTaster_pred=D;MutationAssessor_score=2.485;MutationAssessor_pred=M;FATHMM_score=2.73;FATHMM_pred=T;PROVEAN_score=-4.81;PROVEAN_pred=D;VEST3_score=0.558;CADD_raw=6.549;CADD_phred=31;DANN_score=0.999;fathmm-MKL_coding_score=0.906;fathmm-MKL_coding_pred=D;MetaSVM_score=-0.981;MetaSVM_pred=T;MetaLR_score=0.095;MetaLR_pred=T;integrated_fitCons_score=0.653;integrated_confidence_value=0;GERP++_RS=4.03;phyloP7way_vertebrate=0.917;phyloP20way_mammalian=0.953;phastCons7way_vertebrate=0.997;phastCons20way_mammalian=0.991;SiPhy_29way_logOdds=12.627;ALLELE_END;ANNOVAR_DATE=2017-07-17;Func.refGene=exonic;Gene.refGene=GRIK3;GeneDetail.refGene=.;ExonicFunc.refGene=.;AAChange.refGene=.;avsnp150=.;cosmic70=.;ExAC_ALL=.;ExAC_AFR=.;ExAC_AMR=.;ExAC_EAS=.;ExAC_FIN=.;ExAC_NFE=.;ExAC_OTH=.;ExAC_SAS=.;SIFT_score=.;SIFT_pred=.;Polyphen2_HDIV_score=.;Polyphen2_HDIV_pred=.;Polyphen2_HVAR_score=.;Polyphen2_HVAR_pred=.;LRT_score=.;LRT_pred=.;MutationTaster_score=.;MutationTaster_pred=.;MutationAssessor_score=.;MutationAssessor_pred=.;FATHMM_score=.;FATHMM_pred=.;PROVEAN_score=.;PROVEAN_pred=.;VEST3_score=.;CADD_raw=.;CADD_phred=.;DANN_score=.;fathmm-MKL_coding_score=.;fathmm-MKL_coding_pred=.;MetaSVM_score=.;MetaSVM_pred=.;MetaLR_score=.;MetaLR_pred=.;integrated_fitCons_score=.;integrated_confidence_value=.;GERP++_RS=.;phyloP7way_vertebrate=.;phyloP20way_mammalian=.;phastCons7way_vertebrate=.;phastCons20way_mammalian=.;SiPhy_29way_logOdds=.;ALLELE_END

Solution

  • for example data:

    info1=x;info2=y;xyz=abc;info1=othervalue;info2=.
    

    Assuming that always the first instance of the name is what you want to keep!

    echo "info1=x;info2=y;xyz=abc;info1=othervalue;info2=." |sed -e 's/;/\n/g' |awk -F= '{ if ($1 in words == 0) words[$1]=$2} END { for (w in words) printf"%s=%s;", w, words[w]}'
    

    the result:

    info1=x;info2=y;xyz=abc;
    

    With you will adapt to your data.
    I used gawk v 4.0.2

    Explanation:
    1. sed divides the string into lines at the place where the semicolon occurs,
    2. the -e option means the escape characters can be used
    3. -F = instructs AWK to divide lines into words at the = place
    4. {if ($ 1 in words == 0) words [$ 1] = $ 2} for each line, check if word 1 is in the words array and if not add an element of the word array with the word word1 with the value of word 2
    5. END {...} is done at the end, reads all elements of the array words and then printf prints the keys and values in the expected format