2017-11-26 12 views
-4

配列をソートして特定の列の重複を削除するPerl

col1の最大値のみが残るように配列のcol0の重複行を削除したいとします。データはタブで区切られます。 16の列があります。

sample1_EGFR_19 53 exon19 ... 
sample1_EGFR_19 12  exon20 ... 
sample2_EGFR_19 20  exon19 ... 
sample3_EGFR_20 65  exon20 ... 
sample2_EGFR_19 25  exon12 ... 
sample1_EGFR_20 12  exon20 ... 
sample3_EGFR_20 125 exon20 ... 

所望の出力:

sample1_EGFR_19 53  exon19 ... 
sample1_EGFR_20 12  exon20 ... 
sample2_EGFR_19 25  exon12 ... 
sample3_EGFR_20 125 exon20 ... 

私は、配列を分割し、人口タブ区切りのテキストファイルで始めました。それから私はハッシュを使用し、キーでソートします。最終的な出力は正しくデータがソートされますが、重複は削除されません。最初の列で空白になっている行を削除するにはどうすればよいですか?ありがとう

sample1_EGFR_19 53 exon19 ... 
       12 exon20 ... 
sample2_EGFR_19 25 exon12 ... 
       20 exon19 ... 
sample3 EGFR_20 125 exon20 ... 
       65 exon20 ... 
sample1 EGFR_20 12 exon20 ... 

彼を達成するための簡単な方法を提案してください。おかげ

ここではコードです:

#!/usr/bin/perl 

use strict; 
use warnings; 

use List::MoreUtils qw(uniq); 
use List::Util 'first'; 
use Data::Dumper; 

my $filename  = "/data/Test/output.txt"; 
my $output_filename = "/data/Test/output_changed.txt"; 

my @resultarray; 
my @sorted; 

open(TXT2, "$filename"); 
while (<TXT2>) { 
    push(@resultarray, $_); 
} 
close(TXT2); 

foreach (@resultarray) { 
    chop($_); 
} 

foreach (@resultarray) { 
    print($_); 
    chomp($_); 
    my ($key, $val) = split /\t/, $_, 2; 
    push @{ $result_hash{$key} }, $val; 
} 

foreach (sort { $result_hash{$a} <=> $result_hash{$b} } keys %result_hash) { 
    push(@final_array, $_ . "\t" . join "\t", @{ $result_hash{$_} }); 
} 

undef %{result_hash}; 

foreach (@final_array) { 
    chomp($_); 
    print($_); 
} 

for (0 .. @final_array - 1) { 

    my $myuniquearray = $final_array[$_]; 
    open(MYFILE, ">>$output_filename"); ##opens files with header and adds the rest of the lines. 

    print MYFILE $myuniquearray . "\n"; 
    close(MYFILE); 
} 
+0

'プッシュ(@resultarray、@linearray)':あなたはおそらく 'プッシュ(@resultarray、\ @linearray)したい' 'か、他の@ resultarray'は1D(とは2Dになります) –

+0

最終的にプリントアウト出力:ARRAY(0x1c3cf00) ARRAY(0x1c98708) ARRAY(0x1c289c8) ARRAY(0x1b0e120) ARRAY(0x1b0e090) ARRAY(0x1b0e198) ARRAY(0x1b0e1b0) – user3781528

+0

私はあなたが内の行を格納することでも、これを行うことができると思います各行のフィールド0をキーとして、配列リファレンスを値としてハッシュします。次に、キーが存在しない場合、またはフィールド1がフィールド1の現在の値より大きい場合にのみ、ハッシュを更新します。ファイルを読み取った後、正しい行のみがハッシュ –

答えて

1

これはかなり簡単なUNIXワンライナーです。なぜそれをPerlで書く必要がありますか?

$ sort -k1,1 -k2,2rn /data/Test/output.txt | awk '!seen[$1]++' | tee /data/Test/output_changed.txt 
sample1_EGFR_19 53 exon19 ... 
sample1_EGFR_20 12 exon20 ... 
sample2_EGFR_19 25 exon12 ... 
sample3_EGFR_20 125 exon20 ... 

これは、各グループからの最初の行を選択するawkを使用して、最初の列の上昇により、第2列の降順と数値によってそれをソート。そのawkステートメントがあまりにも混乱している場合、それはawk 'x != $1 { print; x = $1 }'と同じ機能を持っています。 (teeは、端末にファイルにディスプレイ出力を行を書き込みます。)

あなたが本当にPerlを使用する必要がある場合は、ここで説明する問題に簡単な解決策です:

#!/usr/bin/perl 

use strict; 
use warnings; 

sub sort_func { 
    # sort by the first col asc and then by the second col desc and numeric 
    $a->[0] cmp $b->[0] || $b->[1] <=> $a->[1] 
} 

my %seen; 
print 
    map join("\t", @$_),  # re-join the fields with tabs into the original line 
    grep !$seen{$_->[0]}++, # select the first line of each sorted group 
    sort sort_func   # sort lines using the above sort function 
    map [split /\t/, $_, 3], # split by tabs so we can sort by the first two fields 
    <>;      # read lines from stdin or the filename given by ARGV[0] 

マークファイルを実行可能そしてそのようにそれを使用します。

./sortlines.pl /data/Test/output.txt >/data/Test/output_changed.txt 
関連する問題