2013-07-05 2 views
0

사이트를 수색했는데 놀랍게도 효과가있는 것을 찾을 수없는 것 같습니다. 내 특별한 문제는. 그래서 나는 그것을 게시하고 더 경험이 많은 프로그래머 중 일부가 어떻게 문제를 해결할 수 있는지 보았습니다.파일/배열에서 해시 키를 검색하여 해시 값으로 바꿉니다. 모든 해시 키/값에 대해이 작업을 수행하십시오.

은 내가 특정 라벨 (예를 scaffold1253.1_size81005.6.32799_7496)에 대한 검색을 통해 더 단순화 된 라벨 (예를 scaffold1253로 교체하고 싶다고, 텍스트 파일과 같은 스프레드 시트 (탭으로 구분 된 열이 많은 선)이있다. 1a). 이 레이블은 텍스트 파일의 첫 번째 열에 만 있습니다. 나는 이미 새 레이블에 해당하는 키로 이전 레이블이있는 해시를 갖도록 스크립트를 작성했습니다. 이 해시에는 약 26000 개의 행이 있습니다. 그래서 본질적으로 해시 키를 1 씩 가져 와서 텍스트 파일에서 검색하고 각각의 해시 값으로 바꾸고 싶습니다.

나는 꽤 좋은 서버를 가지고 있기 때문에 너무 복잡하여 첫 번째 열이 특정 프로세스를 가속화 할 수 없다면 ok.

이것은 내가 지금까지 무엇을 가지고 :

use warnings; 



$gtf = './Hc_genome/Hc_rztk_1+2+8+9.augustus.gtf'; 
    open(FASTAFILE2, $gtf); 
    @gtfarray = <FASTAFILE2>; 
    #print @gtfarray; 


my %hash; 
while (<>) 
{ 
    chomp; 
    my ($key, $val) = split /\t/; 
    $hash{$key} .= exists $hash{$key} ? ",$val" : $val; 
} 

#print %hash; 

while (my ($find, $replace) = each %hash) { 
    foreach (@gtfarray){ 
     $_ =~ s/$find/$replace/g; 
     push @newgtf, $_; 
    } 
} 
print @newgtf; 

이 코드가 완료되지 않습니다으로 작동하지 않습니다. 저는 foreach 루프 구조에 문제가 있다고 확신합니다. 미안하지만이 일을하는 다른 방법을 모른다. 누구든지이 파일을 실행하고 교체를 수행하는 더 좋은 방법이 있습니까?

모든 입력 사항을 매우 높이 평가할 것입니다. 감사합니다,

앤드류

다음

@DVK

당신의 while 루프, 그것을 수락하지 왜 어떤 아이디어 구문 오류로 실행하여 개조로 전체 스크립트가 무엇입니까? 다시 한 번 감사드립니다! 여기

use warnings; 

$gtf = './Hc_genome/Hc_rztk_1+2+8+9.augustus.gtf'; 
    open(FASTAFILE2, $gtf); 

my %hash; 
while (<>){ 
    chomp; 
    my ($key, $val) = split /\t/; 
    $hash{$key} .= exists $hash{$key} ? ",$val" : $val; 
} 


while $line (<FASTAFILE2>){ 
    my @fields = split(/\t/, $line); 
    # If you only care about first column, don't need the foreach loop below; 
    # just do the loop insides on $fields[0] 
    foreach my $field (@fields) { 
     $field = $hash{$field} if exists $hash{$field}; 
     print $outfile "$field\t"; # Small bug - will print training \t 
    } 
    print $outfile "\n" 
} 

__END__ 

구문 오류이다 펄 gtf_mod2.pl 라인 14 < ./Hc_genome/header_file.txt 구문 오류 gtf_mod2.pl 근처 '$ 동안 라인 "gtf_mod2.pl 라인에서 구문 오류 23, near "}" 컴파일 오류로 인해 gtf_mod2.pl 실행이 중단되었습니다.

+0

당신은 당신의 대답에 '동안 (내 $ 라인 = )' –

답변

1

처음에는 $find$replace 키/값 쌍을 사용하여 루프를 통해 파일을 모두 소모합니다. 는 동안의 외부로 foreach 루프를 이동하고 을 반복

  • (비싼) 당신의 while 루프의 각 반복하는 동안 읽을

    1. 파일을 엽니 다 :

      두 가지 가능한 해결책이 있습니다에게 (저렴)마다 해시

    예 :

    REPLACE: 
    for my $line (@gtfarray) { 
        while(my ($find, $replace) = each %hash) { 
         if($line =~ s/$find/$replace/g) { 
         push @newgtf, $line; 
         next REPLACE; # skip to next iteration 
         } 
        } 
        # if there was no replacement, push the old line 
        push @newgtf, $line 
    } 
    
  • +0

    감사와 같은 괄호 안에'$의 line'을 넣어해야합니다. 나는 지금 그것을 달리고있다. 수정되는 gtf 파일은 ~ 315000 줄이므로 다소 시간이 걸릴 것입니다. 어떻게되는지 알려 드리겠습니다. 또한 큰 텍스트 파일을 제안 할 때와는 반대되는 방식으로 적은 시간이 걸리므로 아래의 제안을 시도하고 있습니다. – amrezans

    1

    첫 번째 열을 바꿀 파일의 크기는 어느 정도입니까?

    가 50,000 선을의> 경우 하고 더 낫다 : 한 번 해시 파일을 통해

    • 반복 처리를 한 번 기본 파일 을 통해 메모리에

    • 으로 반복을 그 해시를 저장 및 모든 행에 대해 모든 열에 대해 기억 된 해시에서 해당 값을 찾은 다음 해시 값으로 바꾸고 작성하십시오. 즉

    , 첫 @gtfarray = <FASTAFILE2>;를 제거하고 당신의 마지막 while 루프를 대체 :

    while my $line (<FASTAFILE2>) { 
        my @fields = split(/\t/, $line); 
        # If you only care about first column, don't need the foreach loop below; 
        # just do the loop insides on $fields[0] 
        foreach my $field (@fields) { 
         $field = $hash{$field} if exists $hash{$field}; 
         print $outfile "$field\t"; # Small bug - will print training \t 
        } 
        print $outfile "\n"; 
    } 
    

    참고 : 나는 필드가 해시 키의 전체 내용을 포함한다는 가정을 만들고있어 (예를 들어, 데이터 파일에는 "scaffold1253.1_size81005.6.32799_7496"이 포함 된 필드가 포함되지만 "XYZscaffold1253.1_size81005.6.32799_7496 ___ IOU"가있는 필드는 포함되지 않습니다.

    만약 그 가정이 틀리고 당신의 발판 문자열이 더 긴 문자열에 포함되어있을 수 있기 때문에 정말로 정규식을 실행해야한다면, O (N * M) 정규식을 실행하는 것 외에는 여전히 더 좋은 해결책이있을 수 있습니다 : 만약 당신의 비계 문자열이 다음해야 할 일 특정 잘 정의 된 형식 (예 : "scaffoldNNNNN.NNN_sizeNNNNN.NNN.NNNN_NNNN")의 모든 있습니다입니다 :

    데이터 파일의 각 라인에 대한
    • 는 단일 정규식 찾기를 실행하는 것이 패턴, 캡처 그룹 괄호 안의 전체 패턴 :

    • 그런 다음 해시에서 @matches 배열의 모든 값을 찾습니다. 발견되면 일치를 s /// 정규식으로 실행하십시오.

    +0

    그는 대체 할 찾기 값이 첫 번째 열에 있다고 생각합니다. 그래서'foreach' 루프는 불필요하다고 생각합니다.'$ fields [0]'만 확인하십시오. –

    +0

    @ChrisCharley - 데이터 파일의 첫 번째 열이든, 해시 파일의 첫 번째 열이든간에 혼란 스럽습니다.좋은 지적. – DVK

    +0

    죄송합니다. 새 레이블로 교체해야하는 이전 레이블이 포함 된 데이터 파일의 첫 번째 열 (탭으로 구분 된 열)입니다. – amrezans

    0

    Tie::File 일이 될 수 있습니까? 즉, 데이터 파일을 배열로 조작 할 수 있다고 가정합니다.

    use Tie::File; 
    
    my $file = "./Hc_genome/Hc_rztk_1+2+8+9.augustus.gtf"; 
    
    tie @lines, 'Tie::File', $file or die ; 
    for (@lines) { 
    s/Oldlabel/NewLable/g; # Change this to fit 
    } 
    
    untie @lines ; 
    

    Tie::File 효율적인 파일 메모리에 "대신에"변화를 유지하는 트릭의 무리를 않습니다.

    0

    previous post에서 파일을 읽는 동안 단축 된 'id'를 만드는 것이 더 간단하지 않습니까? 그럼 당신은 당신이 당신의 해시를 얻는 다른 파일을 필요가 없을 것입니다.

    다음은 (테스트되지 않은) 코드입니다. (인쇄 명령.을 명령 행의 출력 파일로 보내거나 스크립트에 쓰기 위해 파일을 열어야합니다).

    #!/usr/bin/perl 
    use strict; 
    use warnings; 
    
    my $gtf = './Hc_genome/Hc_rztk_1+2+8+9.augustus.gtf'; 
    open my $FASTAFILE2, "<", $gtf or die "Unable to open '$gtf' for reading. $!"; 
    
    my %seen; 
    
    while (<$FASTAFILE2>) { 
        chomp; 
        my ($id, $val) = split /\t/, $_, 2; 
    
        # copy $id to $prefix and 
        # remove everything after '.1' in $prefix 
        (my $prefix = $id) =~ s/\.1\K.*//; 
    
        if ($seen{$id}) { 
         ++$seen{$id}; 
        } 
        else { 
         $seen{$id} = 'a'; 
        } 
        print "$prefix$seen{$id}\t$val\n"; 
    } 
    
    close $FASTAFILE2 or die "Unable to close '$gtf' from reading. $!"; 
    
    +0

    흠, 그래도 나는 마지막으로 코드를 통해 만든 파일이 필요합니다. 독자적으로 게시하십시오. 또한 이전 게시물에서 사용 된 파일의 일부 비계는 text/gtf 파일에서 건너 뜁니다. 그래서 이것은 어떤 비계가 알파벳보다 앞선 문자로 표시되어야한다고 생각합니다. 그래서 해시로 적절한 레이블을 가져와야했습니다. 본질적으로이 gtf 파일은 이전 게시물의 게놈 내에 주석이 달린 유전자를 포함하고 주석이 달린 유전자가없는 일부 발판이 있기 때문에 일부 레이블/스캐 폴드가 누락되었습니다! 희망은 의미가있다;) – amrezans