我有两个制表符分隔的基因组序列文件(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和匹配总数的次数。
我是编程的新手,我很不知道如何在循环中有匹配时保持计数。任何帮助,将不胜感激。如果我没有说清楚的话,请告诉我。
答案 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);
}