6.4 perl--求相同第一列对应的第二列的平均值

Example:

1 2
1 3
1 5
2 0
2 4
3 5
3 7
3 8

这样的一个example文件,我需要根据第一列同名求出他们对应的第二列的平均值。

背景:

来源于bam文件需要求coverage,而这个文件给的是每条scaffoldd每个碱基上的覆盖,第一列是scaffold的名字,而第二列即为该scaffold每个点对应的覆盖。求得每个点上的覆盖的平均值,我们则认为该scaffold的coverage。

这个脚本的难点在于:

你可以定义第一列为建,第二列为值的哈希,但是你怎么第一列有重名的,你如何做标记,让他不重名?

我写的脚本:

#!/usr/bin/perl
use strict;
use warnings;
my $usage="

#############################################################
coverage.pl
Program:

    This script is used to get the average of the first column!
History:
    2014/07/31  First release  Sam
Example:
   perl /path/way/to/coverage.pl inputfile

##############################################################

";

die $usage if (!defined($ARGV[0])) ;
my ($inputfile,%hash);

$inputfile=$ARGV[0];
open (IN,$inputfile) or die "Can't open $inputfile :$!";

while (){
  chomp;
  my $key;
  if (/(\d+|\w+)\s(\d+|\w+)/) {    #不同的第一列需要注意修改这个捕获
   $key=$1;
   $hash{$key}{$_}=$2;   #创立了二维哈希
   }

 }

close IN;

foreach my $key1 (sort keys %hash) { 
   my ($sum,$num2)=(0,0);
  foreach  my $key2 (sort keys %{$hash{$key1}}){
         $num2++;
         $sum+=$hash{$key1}{$key2};   
    }
  my $mean=sprintf "%.2f",$sum/$num2;
  print "$key1\t$mean\n";
}

Ps:这个是我写的第二个脚本,感谢QQ好友无声的仗义改错,不然得疯了。

刚开始写的时候这个my定义的不清楚,所以老是出问题;

同时注意别拼写错误;

还有$hash{$key}{$_}=$2;以及后面的foreach my $key1 (sort keys %hash)是实在是太亮了。

附上另一个好友帮忙写的一个更简洁的脚本:

#! /usr/bin/perl -w
use strict;
die "perl $0 test \n" unless @ARGV==1;
my $file=shift;
open IN,$file||die;

my %hash;
map{my @p=split;$hash{$p[0]}{$_}=$p[1]}< IN >;
close IN;

foreach my $k(sort keys%hash){

        my $count=0;

        my $sum=0;

        foreach my $v(sort keys %{$hash{$k}}){

                $count++;

                $sum+=$hash{$k}{$v};

        }

   my$mean=sprintf "%.2f",$sum/$count;

print "$k\t",$mean,"\n";

}

#这个脚本map实在太亮了,直接捕获了。

个人公众号,比较懒,很少更新,可以在上面提问题,如果回复不及时,可发邮件给我: tiehan@sina.cn

Sam avatar
About Sam
专注生物信息 专注转化医学