如何按列比较两个文本文件并输出列匹配的次数

时间:2011-11-17 01:38:34

标签: perl

我有两个制表符分隔的基因组序列文件(SAM格式),我想比较它们,看看每个都有多少次测序读数(包含一行)。

以下是输入文件格式的示例:

HWI-AT555:86:D0:6:2208:13551:55125       122     chr1    77028   255     94M555N7M       *       0       0       GTGCCTTCCAATTTTGTGAGTGGAGNACAAGTTCGCTAAAGCTAATGAATGATCTACCACCATGATTGAGTGTCTGAGTCGAATCAAGTGAATTGCTGTTAG   &&&(((((*****++++++++++++!!&)*++++)+++++++++++++++++++++++++*++++++++*****((((((''''''&&&&'''&&&&&&&&   NM:i:3  XS:A:+    NH:i:1

重要的部分是序列读取id,它是第一列(即HWI -.... 55125)。这是我想用来比较两个文件,以便我可以计算重复/副本的数量。

这是我到目前为止所做的:

unless (@ARGV == 2) {
    print "Use as follows: perl program.pl in1.file in2.file\n";
    die;
}

my $in1 = $ARGV[0];
my $in2 = $ARGV[1];

open ONE, $in1;
open TWO, $in2;

my %hash1;
my @hit;    

while (<ONE>){
    chomp;
    my @hit = split(/\t/, $_);
    $hash1{$hit[0]}=1;
}
close ONE;

my @col;

while (<TWO>){
    chomp;
    my @col = split(/\t/, $_);
    if ($col[0] =~ /^H/){  #only valid sequence read lines start with "H"
        print "$col[0]\n" if defined($hash1{$_});   

    }
}
close TWO;

到目前为止,它在hash1中查找匹配,同时逐行浏览第二个文件并打印出任何匹配项。我想要做的是计算找到匹配的次数,然后打印出每个序列ID和匹配总数的次数。

我是编程的新手,我很不知道如何在循环中有匹配时保持计数。任何帮助,将不胜感激。如果我没有说清楚的话,请告诉我。

1 个答案:

答案 0 :(得分:2)

使用零而不是1来初始化%hash1

while (<ONE>){
    chomp;
    my @hit = split(/\t/, $_);
    # Start them as "0" for "no duplicates".
    $hash1{$hit[0]} = 0;
}

然后,在第二个循环中,您可以增加$hash1{$col[0]}

while (<TWO>){
    chomp;
    my @col = split(/\t/, $_);
    # Increment the counter if %hash1 has what we're looking for.
    ++$hash1{$col[0]} if(exists($hash1{$col[0]}));
}

无需检查$col[0] =~ /^H/,因为%hash1只有有效序列的条目,因此您只需对哈希进行exists检查即可。并且您希望查看$hash1{$col[0]}而不是$hash1{$_},因为您只在第一个循环中存储了行的第一部分,$_将拥有整行。此外,如果您只是抓住每一行的第一个字段,则不需要chomp次来电,但它们没有任何危害,因此您可以根据需要保留它们。

这会将%hash1中所有重复的条目作为具有非零值的条目留给您,您可以grep这些条目:

my @dups = grep { $hash1{$_} > 0 } keys %hash1;

然后用他们的计数显示它们:

for my $k (sort @dups) {
    print "$k\t$hash1{$k}\n";
}

您还可以在显示匹配项时检查计数:

for my $k (sort keys %hash1) {
    print "$k\t$hash1{$k}\n" if($hash1{$k} > 0);
}