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