2016-08-12 2 views
0

첫 번째 열에 반복되는 값을 갖는 탭 구분 파일이 있습니다. 첫 번째 열의 단일이지만 반복되는 값은 두 번째 열의 여러 값에 해당합니다. 그것은이 같은 같습니다 첫 번째 열의 시퀀스의 모든 유형에 대해열 ID를 기반으로 파일 구문 분석 : perl

AAAAAAAAAA1  m081216|101|123 
    AAAAAAAAAA1  m081216|100|1987 
    AAAAAAAAAA1  m081216|927|463729 
    BBBBBBBBBB2  m081216|254|260489 
    BBBBBBBBBB2  m081216|475|1234 
    BBBBBBBBBB2  m081216|987|240 
    CCCCCCCCCC3  m081216|433|1000 
    CCCCCCCCCC3  m081216|902|366 
    CCCCCCCCCC3  m081216|724|193 

을, 나는에 해당하는 단지 순서로 파일로 인쇄하려합니다. 파일의 이름에는 첫 번째 열에 반복되는 시퀀스와 두 번째 열에 해당 시퀀스의 수를 포함해야합니다. 위의 예제에서 나는 3 개의 시퀀스를 갖는 3 개의 파일을 가질 것이다. 첫 번째 파일은 "AAAAAAAAAA1.3.txt"같은 이름과 같이 될 것이다 열 때 다음과 같은 : 나는 다른 유사한 질문을 보았다

m081216|101|123 
    m081216|100|1987 
    m081216|927|463729 

하지만,이 해시를 사용하여 대답했다. 열 사이의 관계 수를 유지해야하기 때문에 해시를 사용할 수 없다고 생각합니다. 어쩌면 해시의 해시를 사용할 수있는 방법이 있을까요? 나는 잘 모르겠다. 여기 내 코드가 있습니다.

use warnings; 
    use strict; 
    use List::MoreUtils 'true'; 

    open(IN, "<", "/path/to/in_file") or die $!; 

    my @array; 
    my $queryID; 

    while(<IN>){ 
      chomp; 
      my $OutputLine = $_; 
      processOutputLine($OutputLine); 
    } 


    sub processOutputLine { 
      my ($OutputLine) = @_; 
      my @Columns = split("\t", $OutputLine); 
      my ($queryID, $target) = @Columns; 
      push(@array, $target, "\n") unless grep{$queryID eq $_} @array; 
      my $delineator = "\n"; 
      my $count = true { /$delineator/g } @array; 
      open(OUT, ">", "/path/to/out_$..$queryID.$count.txt") or die $!; 
      foreach(@array){ 
        print OUT @array; 
      } 
    } 
+0

당신은 아마 또한 루프에서 파일 쓰기를 제거 할 수 있습니다, 또는 당신은거야 모든 데이터 라인과 함께 쓰십시오. –

답변

3

해시를 권장합니다. 그러나 동일한 ID와 관련된 모든 시퀀스를 해당 ID 키의 값인 익명 배열에 저장합니다. 이것은 실제로 두 줄의 코드입니다. 귀하의 의견으로

use warnings; 
use strict; 
use feature qw(say); 

my $filename = 'rep_seqs.txt'; # input file name 
open my $in_fh, '<', $filename or die "Can't open $filename: $!"; 

my %seqs; 
foreach my $line (<$in_fh>) { 
    chomp $line; 
    my ($id, $seq) = split /\t/, $line; 
    push @{$seqs{$id}}, $seq; 
} 
close $in_fh; 

my $out_fh; 
for (sort keys %seqs) { 
    my $outfile = $_ . '_' . scalar @{$seqs{$_}} . '.txt'; 
    open $out_fh, '>', $outfile or do { 
     warn "Can't open $outfile: $!"; 
     next; 
    }; 
    say $out_fh $_ for @{$seqs{$_}}; 
} 
close $out_fh; 

나는 그들의 세 줄을 각각 대응, AA..._count.txt 이름을 원하는 파일을 얻을. |으로 구분 된 항목을 분할해야하는 경우 예를 들어이를 작성하는 동안 처리 할 수 ​​있습니다. 우리 push 번, 경우 이미

  • 탭 문제 (공간으로 변환?)가있는 경우

    , ' '이 사용하지

    댓글

    • 핵심 $seqs{$id}에 대한 익명의 배열이 생성됩니다. 의견을 참조하십시오.

    • 파일 핸들이 닫히고 모든 open에 다시 개관, 그래서 필요 때마다


    split의 기본 패턴은 특정 행동을 유발 ' '이다를 닫 없습니다 - 그것은 일치 "인접 연속 공백"및 공백 공백을 생략합니다. 패턴 / /은 단일 공백과 일치하며이 특수 동작은 ' '입니다. split 페이지에 대한 자세한 설명을 참조하십시오. 따라서 split의 경우 약간 관용적 인 경우가 많으므로 불특정 다수의 공백으로 나눌 때는 ' '을 사용하는 것이 좋습니다. 가장 일반적으로 사용되며 기본값입니다. 이 의견과 업데이트를 요청한 Borodin에게 감사드립니다. (원래 게시물의 내용은 /\s+/입니다.)' '$_과 함께 기본이기 때문에이 경우, 우리는 그것을 단축 할 수

    주 조금

    for (<$in_fh>) { 
        chomp; 
        my ($id, $seq) = split; 
        push @{$seqs{$id}}, $seq; 
    } 
    
  • +0

    도움과 통찰력있는 의견을 보내 주셔서 감사합니다. 귀하의 답변에 "close $ fh_in;"이라고 나타났습니다. 정말 "close $ in_fh;"이어야합니다. 또한, 내 질문의 후반에 관해서는, 당신은 그 특정 파일 내에 포함 된 시퀀스의 수와 각 파일의 이름을 추가하는 방법에 어떤 트릭이 있습니까? 당신의 엄청난 도움에 다시 한번 감사드립니다 !!! – Rob

    +0

    @Rob 이러한 의견에 감사드립니다. 나는 파일 핸들에'$ specs_fh'라는 이름을 붙이는 것을 좋아한다. 그리고 이름에 카운트를 추가하는 요구 사항을 잊어 버렸습니다. 이제 추가 할 것입니다. 기여에 감사드립니다. – zdim

    +0

    @Rob 파일 이름에 카운트를 추가했습니다. '스칼라 '는리스트의 길이 (엘레멘트의 수)를 반환하며, 배열 참조는 역 참조 (dereferencing) 인'@ {array_ref}'에 의해리스트로 사용될 수 있으므로 정말 간단하다. 실제로'.'를 원한다면 파일 이름의 수를'_'로 나눕니다. '_'을''. ''로 변경하십시오. – zdim