使用perl连续使用特定数字的三列平均值

时间:2014-03-19 05:22:22

标签: perl

我有一个包含以下5列的输入文件,我希望将列号3,4,5分别平均为3,4,5,直到其第二列值为5,类似于第二列值7和2。

PHE  5  2 4 6
PHE  5  4 6 4
PHE  5  4 2 8
TRP  7  5 5 9
TRP  7  5 7 1
TRP  7  5 7 3
TYR  2  4 4 4
TYR  2  4 4 0
TYR  2  4 5 3

我想要一个像这样的输出

PHE  5  3.3 4   6
TRP  7  5   6.3 4.3
TYR  2  4   4.3 2.3

3 个答案:

答案 0 :(得分:0)

perl -lane'
  $k = join "\t", splice(@F, 0, 2);
  $h{$k}{c}++ or push(@r, $k);
  $h{$k}{t}[$_] += $F[$_] for 0 .. $#F;

  END {
    $, ="\t";
    for (@r) {
      ($t, $c) = @{$h{$_}}{"t", "c"};
      print $_, map sprintf("%.1f", $_/$c)*1, @$t;
    }
  }
' file

输出

PHE     5       3.3     4       6
TRP     7       5       6.3     4.3
TYR     2       4       4.3     2.3

答案 1 :(得分:0)

很好的解决方案mpapec。

我开始使用以下解决方案作为实验,看看我是否可以编写只需要一个for循环的东西,而不需要END块。它代之以6代for循环,是一个完美的例子,说明除非你的目标是混淆,否则永远不会编码。

是的,它使用外部模块。是的,它是我发布过的愚蠢的代码(我希望)。但至少它可能会让某人轻笑。是的,它的确有效! :)

use Array::Transpose;
use List::Util qw(sum max);

use strict;
use warnings;

my $g;
my $l;

print "$_\n" for map {
    join ' ', map {sprintf "%-$_->[0]s", $_->[1]} transpose [$l, $_]
} grep {
    $l = [map {max @$_} transpose [[map {length $_} @$_], $l || ()]]
} [qw(Txt Num Ave Ave Ave)], map {
    my @c = transpose $_;
    [$c[0][0], $c[1][0], map {map {/\./ ? sprintf("%.1f", $_) : $_} sum(@$_) / @$_} @c[2..$#c]]
} map {
    $g && $g->[0][0] eq $_->[0] ? (push @$g, $_) && () : ($g = [$_])
} map {[split]} (<DATA>);

__DATA__
PHE  5  2 4 6
PHE  5  4 6 4
PHE  5  4 2 8
TRP  7  5 5 9
TRP  7  5 7 1
TRP  7  5 7 3
TYR  2  4 4 4
TYR  2  4 4 0
TYR  2  4 5 3

输出

Txt Num Ave Ave Ave
PHE 5   3.3 4   6
TRP 7   5   6.3 4.3
TYR 2   4   4.3 2.3

答案 2 :(得分:0)

不使用模块的脚本。

试试这个......

    #!/usr/bin/env perl
open(DATA, "<input.txt") or die "Couldn't open file file.txt, $!";
my %h=();
my %c=();
print "\n";
while(<DATA>){
    my $temp=$_;
   if($temp=~m/^([A-Z]{3})\s+([\d]+)\s+([\d]+)\s+([\d]+)\s+([\d]+)/is)
   {
        my $key=$1;
        $h{$key}{1} +=$2; 
        $h{$key}{2} +=$3; 
        $h{$key}{3} +=$4;
        $h{$key}{4} +=$5;

        if($c{$key})
        {
                $c{$key}++;
        }
        else
        {
            $c{$key}=1;
        }
   }  
}
foreach $key (sort(keys %h)) {
    #print $key.'='.$h{$key}{1}/$c{$key}." ".$h{$key}{2}/$c{$key}." ".$h{$key}{3}/$c{$key}." ".$h{$key}{4}/$c{$key};
        printf("%s %d %.1f %.1f %.1f", $key, $h{$key}{1}/$c{$key},$h{$key}{2}/$c{$key},$h{$key}{3}/$c{$key},$h{$key}{4}/$c{$key});

    print "\n";
    }
     print "\n";
close(DATA);

______OUTPUT________

   PHE 5 3.3 4.0 6.0
   TRP 7 5.0 6.3 4.3
   TYR 2 4.0 4.3 2.3