2013-10-23 40 views
1

我需要计算我考虑到特定的数据分箱情况后比较两个文件的比较数量。第一个是三列文件(此处为test_counter.txt),其中报告了ID对(ID由|分隔)并且每个ID对具有与其相关的值。在另一个文件(list.pl)中,我有一个简单的ID列表,编号为$id{"ID1"} = 1;。 因此,我需要的是计算每个垃圾箱中test_counter.txt文件中的不同ID(间隔必须等于0.1)并且没有重复(这意味着如果垃圾箱中存在两次ID,我想要只计算一次)。 三个栏文件(test_counter.txt)看起来是这样的:通过perl处理数据后对元素进行计数

d|a -0.1412 
a|a -0.1526 
d|a 0.12 
c|b 0.16596 
b|a 0.221 
c|a 0.21123 
d|b 0.388 
c|b 0.35 
b|d 0.412 
d|a 0.5236 
d|c 0.565 
b|a 0.6174 
a|c 0.65 
c|d 0.678 

list.pl文件是这样的一个:

$id{"a"} = 1; 
$id{"b"} = 1; 
$id{"c"} = 1; 
$id{"d"} = 1; 

我期望的输出是这样的:

-0.9 
-0.8 
-0.7 
-0.6 
-0.5 
-0.4 
-0.3 
-0.2 
-0.1 2 
0 
0.1 4 
0.2 3 
0.3 3 
0.4 2 
0.5 3 
0.6 4 
0.7 
0.8 
0.9 

而且我的代码是:

require("id_pf.pl"); 
    $file = "test_counter.txt"; 
    open(HAN, "< $file") || die "not opening $file"; 
     @row = <HAN>; 
    close(HAN); 
    for($i=0;$i<=$#row;$i++) { 
     chomp($row[$i]); 
     ($ppi,$val) = split(/ /,$row[$i]); 
     ($p1,$p2) = split(/\|/,$ppi); 
     if ($val <-0.9) { 
      $bin= 1;   
     } elsif ($val <-0.8) { 
      $bin = 2; 
     } elsif ($val <-0.7) { 
       $bin = 3; 
     } elsif ($val <-0.6) { 
       $bin = 4; 
     } elsif ($val <-0.5) { 
       $bin = 5; 
     } elsif ($val <-0.4) { 
       $bin = 6; 
     } elsif ($val <-0.3) { 
       $bin = 7; 
     } elsif ($val <-0.2) { 
       $bin = 8; 
     } elsif ($val <-0.1) { 
       $bin = 9; 
    } elsif ($val <-0.0) { 
       $bin = 10; 
     } elsif ($val <0.1) { 
       $bin = 11; 
     } elsif ($val <0.2) { 
       $bin = 12; 
     } elsif ($val <0.3) { 
       $bin = 13; 
     } elsif ($val <0.4) { 
       $bin = 14; 
     } elsif ($val <0.5) { 
       $bin = 15; 
     } elsif ($val <0.6) { 
       $bin = 16; 
     } elsif ($val <0.7) { 
       $bin = 17; 
     } elsif ($val <0.8) { 
       $bin = 18; 
     } elsif ($val <0.9) { 
       $bin = 19; 
    } else { 
     $bin = 20; 
    } 
    if (($id{$p1}) || ($id{$p2})){ 
    $pos[$bin]++; 
} else { 
     } 
    } 
    for ($k=1;$k<=20;$k++) { 
     $bin = ($k/10)-1.05; 
     print "$bin\t$pos[$k]\n"; 
    } 

通过这个代码,我得到这个(错误的)结果:

-0.9 
-0.8 
-0.7 
-0.6 
-0.5 
-0.4 
-0.3 
-0.2 
-0.1 2 
0 
0.1 2 
0.2 2 
0.3 2 
0.4 1 
0.5 2 
0.6 3 
0.7 
0.8 
0.9 

所以,pratically我的代码只能读取第一个ID,但不考虑第二。而另一个错误是,它会在出现在箱中的次数中统计出一个ID。 任何帮助非常欢迎!

回答

3

按照评论进行编辑。现在应该工作。

use strict; 
use warnings; 
use 5.14.0; 

my %hash; 
while(<DATA>){ 
    next if /^\s*$/m; # In case if you have empty lines. 
    my ($key1,$key2,$val) = /^(\w)\|(\w) ([0-9.-]+)/; 
    $val = int($val*10)/10; 
    $hash{$val}{$key1}++; 
    $hash{$val}{$key2}++; 
} 
for (-9..9){ 
    $_ = $_/10; 
    say "$_\t",ref $hash{$_} ? scalar keys $hash{$_} : ''; 
} 

__DATA__ 
d|a -0.1412 
a|a -0.1526 
d|a 0.12 
c|b 0.16596 
b|a 0.221 
c|a 0.21123 
d|b 0.388 
c|b 0.35 
b|d 0.412 
d|a 0.5236 
d|c 0.565 
b|a 0.6174 
a|c 0.65 
c|d 0.678 

输出:

-0.9  
-0.8  
-0.7  
-0.6  
-0.5  
-0.4  
-0.3  
-0.2  
-0.1 2 
0 
0.1 4 
0.2 3 
0.3 3 
0.4 2 
0.5 3 
0.6 4 
0.7 
0.8 
0.9 
+0

你的代码能正常工作,我写到这里的例子,但如果数据值有两个或两个以上的十进制数它不能正常打印。5月你建议什么? – Gabelins

+0

然后你必须完全改变'for'循环。我想最好的办法是循环散列键:'为我的$键(排序键%散列){...}' –

+0

我想尝试像你所建议的,唯一的问题,我不能bin数据。如果我修改我的输入文件,你可以帮我吗? – Gabelins

相关问题