我有一个制表符分隔文件,例如
Name S.No Points First
Jack 2 98 F
Jones 6 25
Mike 8 11
Jasmine 5 7
Gareth 1 85 F
Simon 4 76
Mark 11 12
Steve 17 8
Clarke 3 7
我想计算前3名收入者以及由F行表示的第一个收入者与该组中其他两个人的平均值之间的差异。例如,琼斯和迈克在第一种情况下,西蒙和马克在第二种情况下。我希望我的输出是
Name S.No Points First
Jack 2 98 F
Jones 6 25 51.77
Mike 8 11 61.70
Gareth 1 85 F
Simon 4 76 4.78
Mark 11 12 44.68
计算百分比的公式在输出的最后一列是,例如在情况1中的琼斯的情况下是
(Jack - Jones)*100/(Jack + Jones + Mike + Jasmine)
(98-25)*100/(98+25+11+7)= 51.77
我可以使用
选择前三个顶行awk '$NF~/E/{c=3;next}c-->0'
但是,计算差异和百分比比较繁琐,因为我必须在消除前三行之前对分母求和。
答案 0 :(得分:2)
参考你的awk命令,似乎源文件已经按组对数据进行了排序。
awk 'NR==FNR{if ($NF=="F") {s=$1}; a[s]+=$3;next}
{ if (FNR=="1") {print;next}
if ($NF=="F") {s=$1;b=$3;c=3;print;next}
if (--c>0){ printf "%s %.2f\n", $0,(b-$3)*100/a[s];}
}' file file
结果
Name S.No Points First
Jack 2 98 F
Jones 6 25 51.77
Mike 8 11 61.70
Gareth 1 85 F
Simon 4 76 4.79
Mark 11 12 38.83
答案 1 :(得分:1)
获得完全不同的Mark号码:
use 5.010;
use strict;
use warnings;
use autodie;
use List::Util 'sum';
open my $infile, '<', 'foo.txt';
my @groups;
my $group;
while ( my $line = <$infile> ) {
chomp $line;
my ($name, $sno, $points, $first) = split /\t/, $line;
if ( $first && $first eq 'F' ) {
$group = [];
push @groups, $group;
}
push @$group, { 'name' => $name, 'sno' => $sno, 'points' => $points, 'first' => $first };
}
say join "\t", qw/Name S.No Points First/;
for my $group (@groups) {
my $total_points = sum map $_->{'points'}, @$group;
my $first_points = $group->[0]{'points'};
say join "\t", @{ $group->[0] }{ qw/name sno points first/ };
for my $other (1..2) {
if ( $group->[$other] ) {
say join "\t", @{ $group->[$other] }{ qw/name sno points/ }, sprintf "%.2f", 100 * ($first_points - $group->[$other]{'points'}) / $total_points;
}
}
}
产生
Name S.No Points First
Jack 2 98 F
Jones 6 25 51.77
Mike 8 11 61.70
Gareth 1 85 F
Simon 4 76 4.79
Mark 11 12 38.83
答案 2 :(得分:1)
这是一个awk解决方案:
awk -f c.awk input.txt input.txt
其中c.awk
是:
NR==FNR {
if ($NF=="F") {
key1=$1
A[key1]=$3
B[key1]=$3
}
else if (key1)
B[key1]+=$3
next
}
key && NF==3 {
if (++k<3) {
$4=((A[key]-$3)*100)/B[key]
print
}
next
}
$NF=="F" {
key=$1
k=0
}
{print}