Perl:查找哈希值和计算平均值的最大值

时间:2012-12-19 09:18:55

标签: arrays perl hash bioinformatics

经过大约6个月的休整后,我回到了Perl和生物信息学的世界,在一位不同的科学家的带领下实习。但是第一次任务不同于我上次遇到的任何一项任务,所以虽然我取得了一些进展,但我还没能完全解决这个问题。我也试图尽快修改我上次学到的东西,因为在过去的6个月里我完全失去了编程的机会。 数据集如下所示:

NR_046018   DDX11L1     ,   0   0   1   1   1   1   1   1   1   1   0   0   0   0   1.44    2.72    3.84    4.92    5.6 6.64    7.08    9.12    9.56    8.28    7.16    6.08    5.4 4.36    3.92    1.88    0   0   0.76    1   1   1   1.2 2   2   2   1.72    2   2   2   1.8 1   1.88    2.4 3   3.36    5   6   6   6.72    6.12    5.6 5.44    5.56    5   4.04    5   4.28    4   4   3.08    2.08    1.68    1.96    1.44    3   3.68    4   4.16    5   4.32    4.8 6.16    6   6.28    6.92    7.84    7   7.32    7.2 5.96    5   4.52    4.08    3   3   4.04    4.12    4.44    4   3.52    3.4 4   4   2.64    1.88    1   1   1   0.64    1   1   1.24    2   2.92    3   3   2.96    2   2   2.56    2   1.08    2.12    3   3   3   3   2.6 3   4.64    3.88    3.72    4   4   4.96    4.6 4   2.36    2   1.28    1   1   0.04    0   0.24    1.08    2.68    3.84    4.12    5.72    6   6   5.76    4.92    3.32    3.12    2.88    2.08    2   2   2   2   2   1.44    2.92    3.04    4.28    5.8 7.8 9.48    10.52   13.04   12.08   11.6    11.72   11  9.2 7.52    7.12    7.08    7.08    8.32    7   6.6 7.6 8.04    8.36    6.72    7.88    7.72    8.4 9.24    8.88    8.96    9.88    10.08   9.24    9.28    10.16   11.04   10.52   10  8.56    8   7.8 7.72    6.44    4.32    4   4   3.72    3.68    3.68    3.28    5.56    7.36    9.48    10  10.52   11  12.16   11.96   9.44    8.64    7.52    7   6.48    6   5   5.12    6.28    6   5.52    6   6.68    6.08    7.52    8.16    7.72    8.52    8.56    9.2 9.16    8.92    7.44    6   5   3.48    2.92    2.16    2   2   1.2 1   1   1   1.24    1.64    1   1   1.96    2   2   2   1.76    1   1   1   0.52    1.76    3.64    5.12    6   6   6   6   5.52    4.24    2.36    0.88    0   0   0.68    1   1   1   1   1   1   1   0.32    0   0   1   1   1.44    2.44    3.68    5.4 6.88    7   6   6.52    6.76    6.56    5.32    3.6 2.92    3   3.72    3.96    3.8 3   3   3   2.2 2.4 2.28    1.52    1   1   1   1.72    2   1.6 1   1   1   1   1   0.28    0.92    2   2   2.72    3.64    4   4.84    5   4.08    3   3   2.68    2.36    2   1.16    1   1   2   4.92    4.6 4   4   4   4   4.32    4   1.08    1   1.52    2   2   2   1.68    1   1   1.32    1.48    1   1   1.52    2   2   2   1.68    1   1   1.88    1.48    1   1   1   1   1   1   0.12    0.4 1   1   1.2 3.88    4   5   5   4.6 4   4   3.8 2.08    2   1   1   1.44    2.4 3
NR_047520   LOC643837   ,   3   2.2 0.2 0   0   0.28    1   1   1   1   2.2 4.8 5   5.32    5   5   5   5   3.8 1.2 1   0.4 0   0   0   0   0   1   1   1   1   1   1   1   1.56    1   1   1   1   1   1   1   0.44    0.68    1   1.52    3   3.6 4.96    6.8 9   8.32    8.72    8.48    7   7.4 8.8 7.92    7.12    8.84    8.56    9.4 10.2    10  7.24    6.44    6.76    6.16    5.72    4.96    4.8 5.16    6   5.84    4.12    3   3   2.64    2.56    3.08    3   4.16    5   6.72    7   7.16    7.44    5.76    5   4.56    4   3.68    5   5.4 5.52    6   6   5.28    5   3.6 2   2.08    1.48    1   2   2   2   2   2   1.36    1   1   0   0   0.68    1   1   1   1   1   1   1   0.32    0   0   0   1.16    2   2   2   2   2.88    3   3   1.84    1   2   2   2.04    2.12    2   2   2   2   1   1.28    1.96    1.36    2.76    3   3   3   3   2.72    2   1.64    0.76    1   1.36    2   2   2   2   2   1.48    1   0.64    0   0.08    1   1   1.08    2   2   2   2   2.68    2   2   2.16    3.4 4   4   4.2 4.24    4   5.68    6.52    4.6 4   4   3.8 3.8 4   3.12    2.24    2.6 3   4   4   3.2 3   2.2 2   1.4 1.84    1.24    2   2   2   2   2   2   1.16    0.76    0   0   0   0   0   0   0   0.36    1   1.68    2   2   2.92    5.4 6.76    7.64    7   6.88    7   7.36    7.92    6.24    5.92    7.04    9.52    11.52   12.88   14.8    16.36   19.88   22.24   20  19.36   16.92   15.24   13.84   10.88   8.24    5.08    4.96    3.12    3   2.88    2   2.8 2.96    4   4.44    5   6   6   6   5.12    3.28    2   1.56    1   0.08    1.68    2   2   2.84    3   3   3.8 3.92    2.32    2   2.2 2.16    2   2   1.2 1   1   1   0.8 0   0   0   0.72    2.88    3   3   3   3   3   3   2.28    0.12    0   0.52    1   1   1   1   1.44    2   2   1.48    1   1   1   1.56    1.56    1   1   1   1   1   1   0.44    0.8 1.48    3   3   3   3   3   3.56    3.2 2.76    2   2   2   2   2.68    2.44    2   1.76    1   1.4 2   2   1.56    2   2   2   2   2.04    2   2   1.76    1   1   1   1   0.56    0   0   0   0   0   0   0   0   0.72    1.52    2   2   2   2   2   2   1.28    0.48                                                                            

1。需要什么

  1. 对于数据文件中的每一行,从数字范围中查找最大值。
  2. 找到所有行的最大值后,找到平均最大值。
  3. 2。策略我在想

    1. 将非数字部分与非数字部分分隔为哈希的"键"
    2. 将数字部分放入哈希的"值" 中。
    3. "值" 分配到数组@values
    4. 使用模块use List::Util qw(max)查找数组中的最大值
    5. 将这些最大值存储在另一个数组中,并从此数组中查找平均值。
    6. 第3。到目前为止编写的代码

      use warnings;
      use List::Util qw(max);
      
      #Input filename
      $file = 'test1.data';
      
      #Open file
      open I, '<', $file or die;
      
      #Separate data into keys and values, based on ','
      chop (%hash = map { split /\s*,\s*/,$_,2 } grep (!/^$/,<I>));
      print "$_ => $hash{$_}\n" for keys %hash; #Code is working fine till here
      
      #Create a values array
      @values = values %hash;
      foreach $value(@values){
       print "The values are : ", $value,"\n";
      }
      

      4。问题

      除此之外,我无法弄清楚如何添加每个"individual"数组 将元素转换为新数组,以便我可以使用max函数。

      我的意思是,例如,first array element中的@values包含0 0 1 1 3 4.4等数据。 second array element可能包含3 2.2 0.28 1 1 4.8等数据。所以我需要将each这些数组元素放入一个新数组中,每个元素进入不同的数组,这样我就可以使用{ {1}}功能。

      5。注意事项

      1. 大多数行包含400个数字,有些行数少于此数字,但从不超过400个。

      2. 共有23,558行。

      3. 文件是.txt文件,每行中的所有数字都以制表符分隔。
      4. 我将非常感谢任何能够指出我正确方向的人,或者提供更好的代码来解决 1中提到的问题。

2 个答案:

答案 0 :(得分:7)

如果我正确理解你的问题,你会让它变得过于复杂:

#!/usr/bin/env perl
use strict;
use warnings;
use List::Util qw(max);

#Input filename
my $file = 'test1.data';

#Open file
open my $fh, '<', $file or die "Unable to open $file: $!\n";

my ($total, $num);

while (<$fh>) {
    my @values = split;
    my $max = max(@values[3 .. $#values]);
    $total += $max;
    $num++;
}

my $average_max = $total / $num;

只需对文件进行一次传递,将这些行拆分为一个数组并提供从索引3max的所有内容。为每一行添加$max$total,增加一个计数器($num)并计算其平均最大值。

您还应始终使用use strict和词法文件句柄。

答案 1 :(得分:1)

这是一个有趣的解决方案。如果您使用List::Util,也可以使用sum

#!usr/bin/perl
use strict;
use warnings;
use List::Util qw/max sum/;

my %line_max = map {
    /([\w\s]*?)\s*,\s*(.*)/ or die "bad line";
    $1 => max split ' ', $2
} <DATA>;

print "$_: $line_max{$_}\n" foreach (keys %line_max);

my $avg_max = sum (values %line_max) / scalar (values %line_max);
print "average: $avg_max\n";

__DATA__
NR_046018   DDX11L1     ,   0   0   1   1   1   1   1   1   1   1   0   0   0   0   1.44    2.72    3.84    4.92    5.6 6.64    7.08    9.12    9.56    8.28    7.16    6.08    5.4 4.36    3.92    1.88    0   0   0.76    1   1   1   1.2 2   2   2   1.72    2   2   2   1.8 1   1.88    2.4 3   3.36    5   6   6   6.72    6.12    5.6 5.44    5.56    5   4.04    5   4.28    4   4   3.08    2.08    1.68    1.96    1.44    3   3.68    4   4.16    5   4.32    4.8 6.16    6   6.28    6.92    7.84    7   7.32    7.2 5.96    5   4.52    4.08    3   3   4.04    4.12    4.44    4   3.52    3.4 4   4   2.64    1.88    1   1   1   0.64    1   1   1.24    2   2.92    3   3   2.96    2   2   2.56    2   1.08    2.12    3   3   3   3   2.6 3   4.64    3.88    3.72    4   4   4.96    4.6 4   2.36    2   1.28    1   1   0.04    0   0.24    1.08    2.68    3.84    4.12    5.72    6   6   5.76    4.92    3.32    3.12    2.88    2.08    2   2   2   2   2   1.44    2.92    3.04    4.28    5.8 7.8 9.48    10.52   13.04   12.08   11.6    11.72   11  9.2 7.52    7.12    7.08    7.08    8.32    7   6.6 7.6 8.04    8.36    6.72    7.88    7.72    8.4 9.24    8.88    8.96    9.88    10.08   9.24    9.28    10.16   11.04   10.52   10  8.56    8   7.8 7.72    6.44    4.32    4   4   3.72    3.68    3.68    3.28    5.56    7.36    9.48    10  10.52   11  12.16   11.96   9.44    8.64    7.52    7   6.48    6   5   5.12    6.28    6   5.52    6   6.68    6.08    7.52    8.16    7.72    8.52    8.56    9.2 9.16    8.92    7.44    6   5   3.48    2.92    2.16    2   2   1.2 1   1   1   1.24    1.64    1   1   1.96    2   2   2   1.76    1   1   1   0.52    1.76    3.64    5.12    6   6   6   6   5.52    4.24    2.36    0.88    0   0   0.68    1   1   1   1   1   1   1   0.32    0   0   1   1   1.44    2.44    3.68    5.4 6.88    7   6   6.52    6.76    6.56    5.32    3.6 2.92    3   3.72    3.96    3.8 3   3   3   2.2 2.4 2.28    1.52    1   1   1   1.72    2   1.6 1   1   1   1   1   0.28    0.92    2   2   2.72    3.64    4   4.84    5   4.08    3   3   2.68    2.36    2   1.16    1   1   2   4.92    4.6 4   4   4   4   4.32    4   1.08    1   1.52    2   2   2   1.68    1   1   1.32    1.48    1   1   1.52    2   2   2   1.68    1   1   1.88    1.48    1   1   1   1   1   1   0.12    0.4 1   1   1.2 3.88    4   5   5   4.6 4   4   3.8 2.08    2   1   1   1.44    2.4 3
NR_047520   LOC643837   ,   3   2.2 0.2 0   0   0.28    1   1   1   1   2.2 4.8 5   5.32    5   5   5   5   3.8 1.2 1   0.4 0   0   0   0   0   1   1   1   1   1   1   1   1.56    1   1   1   1   1   1   1   0.44    0.68    1   1.52    3   3.6 4.96    6.8 9   8.32    8.72    8.48    7   7.4 8.8 7.92    7.12    8.84    8.56    9.4 10.2    10  7.24    6.44    6.76    6.16    5.72    4.96    4.8 5.16    6   5.84    4.12    3   3   2.64    2.56    3.08    3   4.16    5   6.72    7   7.16    7.44    5.76    5   4.56    4   3.68    5   5.4 5.52    6   6   5.28    5   3.6 2   2.08    1.48    1   2   2   2   2   2   1.36    1   1   0   0   0.68    1   1   1   1   1   1   1   0.32    0   0   0   1.16    2   2   2   2   2.88    3   3   1.84    1   2   2   2.04    2.12    2   2   2   2   1   1.28    1.96    1.36    2.76    3   3   3   3   2.72    2   1.64    0.76    1   1.36    2   2   2   2   2   1.48    1   0.64    0   0.08    1   1   1.08    2   2   2   2   2.68    2   2   2.16    3.4 4   4   4.2 4.24    4   5.68    6.52    4.6 4   4   3.8 3.8 4   3.12    2.24    2.6 3   4   4   3.2 3   2.2 2   1.4 1.84    1.24    2   2   2   2   2   2   1.16    0.76    0   0   0   0   0   0   0   0.36    1   1.68    2   2   2.92    5.4 6.76    7.64    7   6.88    7   7.36    7.92    6.24    5.92    7.04    9.52    11.52   12.88   14.8    16.36   19.88   22.24   20  19.36   16.92   15.24   13.84   10.88   8.24    5.08    4.96    3.12    3   2.88    2   2.8 2.96    4   4.44    5   6   6   6   5.12    3.28    2   1.56    1   0.08    1.68    2   2   2.84    3   3   3.8 3.92    2.32    2   2.2 2.16    2   2   1.2 1   1   1   0.8 0   0   0   0.72    2.88    3   3   3   3   3   3   2.28    0.12    0   0.52    1   1   1   1   1.44    2   2   1.48    1   1   1   1.56    1.56    1   1   1   1   1   1   0.44    0.8 1.48    3   3   3   3   3   3.56    3.2 2.76    2   2   2   2   2.68    2.44    2   1.76    1   1.4 2   2   1.56    2   2   2   2   2.04    2   2   1.76    1   1   1   1   0.56    0   0   0   0   0   0   0   0   0.72    1.52    2   2   2   2   2   2   1.28    0.48                                                            

注意:map语法很可爱,但如果文件很大,您应该使用while循环来提高效率。 while循环避免将整个文件读入内存:

while (<DATA>)
{
    if (/^([\w\s]*?)\s*,\s*(.*)/)
    {
        $line_max{$1} = max split ' ', $2;  
    }
    else
    {
        print "Line $. is bad.\n";  
    }   
}