2017-11-26 1 views
-4

배열 정렬 및 특정 열의 중복 제거 Perl

col 1의 최대 값만 남도록 배열의 col 0에서 중복 행을 제거하고 싶습니다. 데이터는 탭으로 구분됩니다. 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를 이용한다. 그 awk 문장이 너무 혼란 스럽다면 awk 'x != $1 { print; x = $1 }'과 같은 기능을합니다. (tee는 단말기에 파일에 디스플레이 출력을 선을 기록합니다.)

당신이 정말로 펄을 사용해야하는 경우가 여기에 설명 된 문제에 대한 간단한 해결책 :

#!/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