在我的数据集中有2列,第一列是“参考”列,第二列是“值”列。参考值可以重复多次,但每个参考值都有不同的值。
e.g。
ref1 0.0234
ref1 2.8951
ref1 1.4565
ref2 20.346
ref2 24.345
我需要创建一个脚本,该脚本将包含每个引用ID的最高值的行,并将其放在一个新文件中。对于我的示例,新文件看起来像:
ref1 2.8951
ref2 24.345
答案 0 :(得分:1)
我会使用awk执行此任务:
$ awk '$2+0>a[$1]{a[$1]=$2;b[$1]=$0}END{for (i in a) {print b[i]}}' infile
ref1 2.8951
ref2 24.345
Perl非常有用,但在我看来,对于这个简单的任务,你无法击败awk简单。
这是内部,当第二列大于为该引用存储的先前值($ 1)时,我们保留/更新两个结构(哈希):
在END部分,我们负责显示结果,因此我们将最大参考值与其线条相关联。
答案 1 :(得分:1)
这是一种方法:
$ perl -anle '
$h{$F[0]} = $F[1] > $h{$F[0]}
? $F[1]
: $h{$F[0]}
;
END {print "$_ $h{$_}" for sort keys %h}
' file
ref1 2.8951
ref2 24.345
<强>解释强>
%h
:
%h
中id的值,我们将值更新为hash,否则保持当前值。%h
中打印键,值对,按键顺序排序。答案 2 :(得分:1)
klashxx的解决方案很接近,但额外的阵列确实没有必要。
awk '$2+0 > a[$1] {
a[$1] = $2
}
END {
for (i in a) {
print i, a[i]
}
}' ref
在我看来,awk
是这项工作的“正确”工具,因为它是为处理这样的记录中的数据而构建的。虽然我建议您阅读awk
以获得该计划的全部要点,但这里有一些解释,以便了解正在发生的事情。
awk
遍历文件中的所有行并对其进行操作。花括号中的第一个块包含仅在第二个字段($ 2)大于该数组中该参考值的已保存值的值的行上的操作。 +0强制转换为数值。在此块中,然后将$ 2值分配给数组a,其索引为参考值。
只有在读取文件中的所有行后,才会调用END块。它遍历您拥有的数组,并从数组中打印索引和值。
答案 3 :(得分:0)
你可以这样做:
perl -alne '
unless (defined($h{$F[0]})){
$h{$F[0]}=0
}
if($h{$F[0]} <= $F[1] ){
$h{$F[0]}=$F[1]
}END{
foreach( keys %h){print "$_ $h{$_}"}
}' file
ref1 2.8951
ref2 24.345
全部在一行:
perl -alne 'unless (defined($h{$F[0]})){ $h{$F[0]}=0}; if($h{$F[0]} <= $F[1] ){$h{$F[0]}=$F[1];}END{foreach( keys %h){print "$_ $h{$_}"}}' file
ref1 2.8951
ref2 24.345
答案 4 :(得分:0)
即使它已被回答,我也会肛门并按照信中的说明制作一个实际的perl脚本:
#!/usr/bin/perl
use warnings;
use strict;
unless ($ARGV[0]) { die "Missing source file as first arguement\n" }
unless ($ARGV[1]) { die "Missing destination file as second arguement\n" }
unless (-e $ARGV[0]) { die "Filename $ARGV[0] not found\n" }
if (-e $ARGV[1]) { die "Cowardly refusing to overwrite $ARGV[1]\n" }
open OLD,"<$ARGV[0]" or die "Couldn't open file: $!";
my %refs;
while (<OLD>)
{
my ($ref, $value) = split(/\s+/,$_);
if ($refs{$ref})
{
if ($value > $refs{$ref}) { $refs{$ref} = $value }
} else { $refs{$ref} = $value }
}
open NEW,">>$ARGV[1]";
foreach my $ref (keys(%refs))
{
print "$ref\t$refs{$ref}\n";
print NEW "$ref\t$refs{$ref}\n";
}
%refs
跟踪每个ref的最高值,因为while
- 循环遍历文件。 %refs
中存储的值检查值,如果更高则更新。 不像其他一些建议一样干净和紧凑,但对于不熟悉perl的人来说应该易于阅读和编辑。