如何使用 Perl 对相等的值进行分组并打印最小和最大参数?
Posted
技术标签:
【中文标题】如何使用 Perl 对相等的值进行分组并打印最小和最大参数?【英文标题】:How can I group equal values and print the minimum and maximum parameters with Perl? 【发布时间】:2012-12-27 04:52:53 【问题描述】:我有这个输入数据:
miRNA17 dvex571195 207 230
miRNA17 dvex571195 189 229
miRNA17 dvex571195 207 241
miRNA17 dvex571195 207 230
miRNA17 dvex571195 80 111
miRNA18 dvex449276 12 43
miRNA18 dvex196735 2909 2929
miRNA18 dvex765590 183 213
miRNA22 dvex826214 206 236
miRNA23 dvex529006 111 168
miRNA24 dvex803612 317 347
我想对具有相同 First 和 Second 值的行进行分组。接下来,使用这个“组”,我需要在第三列中打印“组”的最小值,并在第四列中打印“组”的最大值。输出将是:
miRNA17 dvex571195 80 241
miRNA18 dvex449276 12 43
miRNA18 dvex196735 2909 2929
miRNA18 dvex765590 183 213
miRNA22 dvex826214 206 236
miRNA23 dvex529006 111 168
miRNA24 dvex803612 317 347
我尝试将所有数据分组到一个大的 %Hash 中,我的键由第一列和第二列表示。但是我可以使用一种方法来组织后续的列。代码是:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my %lines; # hash with 1rd and 2th elements as key
my %first_line_per_group; # stores in which line a group appeared first
while(my $line = <>)
# remove line break
chomp $line;
# retrieve elements form line
my @elements = split /\s+/, $line;
# build key from elements 1 and 2 (array 0-based!)
my $key = $elements[0]." ".$elements[1];
if(! $lineskey)
#my $min = max $elements[3];
$first_line_per_group$key = $elements[0]."\t".$elements[1];#."\t".$min;
push @ $lines$key , $line;
# the result:
for my $key (keys %lines)
print $first_line_per_group$key."\t";
print "$_\n" for @ $lines$key ;
这段代码的输出是:
miRNA17 dvex571195 miRNA17 dvex571195 207 230
miRNA17 dvex571195 189 229
miRNA17 dvex571195 207 241
miRNA17 dvex571195 207 230
miRNA17 dvex571195 80 111
miRNA18 dvex449276 miRNA18 dvex449276 12 43
miRNA18 dvex196735 miRNA18 dvex196735 2909 2929
miRNA18 dvex765590 miRNA18 dvex765590 183 213
miRNA22 dvex826214 miRNA22 dvex826214 206 236
miRNA23 dvex529006 miRNA23 dvex529006 111 168
miRNA24 dvex803612 miRNA24 dvex803612 317 347
但我需要消除分组值并完成上述工作。
【问题讨论】:
您想要的输出保留第一行的顺序;这是故意的,还是可以接受排序? 【参考方案1】:您只缺少一件事:当$lineskey
为真时,您想调整$first_line_per_group$key
使其值包含组的最小值和最大值。
经过一些清理,您最终得到以下代码:
my %groups;
while (<>)
my @f = split;
my $key = "$f[0] $f[1]";
if ($groups$key)
$f[2] = $groupskey[2] if $groupskey[2] < $f[2];
$f[3] = $groupskey[3] if $groupskey[3] > $f[3];
$groups$key = \@f;
for my $key (keys(%groups))
print(join(' ', @ $groups$key ), "\n");
【讨论】:
“清理后”是什么意思? 我不确定你在问什么。也许我刚刚做的小修改有帮助? 终于明白了。解决方案很棒。非常感谢!!【参考方案2】:您可能想看看这个程序,它似乎可以满足您的需求。
我不清楚您的文件是制表符分隔的还是只是空格分隔的,但只要值中没有空格就没有关系。我已经在空格上分割了每条记录,因为这就是您的代码所做的。
use strict;
use warnings;
use List::Util qw/ min max /;
my %data;
while (<>)
my @fields = split;
push @ $data"@fields[0,1]" , [ @fields[2,3] ];
for my $key (sort keys %data)
my $val = $data$key;
print join(' ', $key, min(map $_->[0], @$val), max(map $_->[1], @$val)), "\n";
输出
miRNA17 dvex571195 80 241
miRNA18 dvex196735 2909 2929
miRNA18 dvex449276 12 43
miRNA18 dvex765590 183 213
miRNA22 dvex826214 206 236
miRNA23 dvex529006 111 168
miRNA24 dvex803612 317 347
【讨论】:
以上是关于如何使用 Perl 对相等的值进行分组并打印最小和最大参数?的主要内容,如果未能解决你的问题,请参考以下文章