1

私はこの入力データを持っています:

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 の値が同じ行をグループ化したい。次に、この「グループ」を使用して、3 列目に「グループ」の最小値を出力し、4 列目に「グループ」の最大値を出力する必要があります。出力は次のようになります。

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 にグループ化しようとしましたが、キーは最初と 2 番目の列で表されます。しかし、後続の列を整理する方法を使用できます。コードは次のとおりです。

#!/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(! $lines{key}) {
    #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

しかし、グループ化された値を削除して、上記の作業を行う必要があります。

4

2 に答える 2

3

足りないのは1つだけです。$lines{key}がtrueの場合、$first_line_per_group{$key}その値にグループの最小値と最大値が含まれるように調整する必要があります。

いくつかのクリーンアップの後、次のコードになります。

my %groups;
while (<>) {
   my @f = split;
   my $key = "$f[0] $f[1]";

   if ($groups{$key}) {
      $f[2] = $groups{key}[2] if $groups{key}[2] < $f[2];
      $f[3] = $groups{key}[3] if $groups{key}[3] > $f[3];
   }

   $groups{$key} = \@f;
}

for my $key (keys(%groups)) {
   print(join(' ', @{ $groups{$key} }), "\n");
}
于 2013-01-12T21:31:35.407 に答える
1

このプログラムを見てみるといいかもしれません。これは必要なことを行っているようです。

ファイルがタブで区切られているのか、空白で区切られているだけなのかはわかりませんが、値にスペースが含まれていない限り問題ありません。それがあなたのコードが行うことであるため、空白で各レコードを分割しました。

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
于 2013-01-13T05:51:26.037 に答える