첫 번째 열을 기반으로 여러 파일을 병합하고 메모리 문제를 저장합니다.

첫 번째 열을 기반으로 여러 파일을 병합하고 메모리 문제를 저장합니다.

탭으로 구분된 fastq 파일이 여러 개 있습니다. 각 읽기의 두 번째 줄을 일치시키고 일치하면 그 옆에 있는 값을 더하고 싶습니다. 예를 들어:


file1.fq
>1
ATGCCGTT      file1:1
+
HHHHKKKK

file2.fq
>2
ATGCCGTT       file2:3
+
JJKHHTTT

>3
ATTCCAAC        file2:1
+
=#GJLMNB

내가 원하는 출력은 다음과 같습니다.


output.txt

ATGCCGTT      file1:1    file2:3     count:4
ATTCCAAC      file2:1          count:1

내가 작성한 코드는 다음과 같습니다.



#!/usr/bin/env perl
use strict;
use warnings;
no warnings qw( numeric );
my %seen;


$/ = "";
while () {
    chomp;
    my ($key, $value) = split ('\t', $_);

    my @lines = split /\n/, $key;
    my $key1 = $lines[1];

    $seen{$key1} //= [ $key ];
    push (@{$seen{$key1}}, $value);

}

foreach my $key1 ( sort keys %seen ) {
my $tot = 0;
my $file_count = @ARGV;
for my $val ( @{$seen{$key1}} ) {
        $tot += ( split /:/, $val )[0];
    }   

if ( @{ $seen{$key1} } >= $file_count) {


        print join( "\t", @{$seen{$key1}});
        print "\tcount:". $tot."\n\n";
    }
}

이 코드는 작은 파일에는 잘 작동하지만 큰 파일을 비교하려고 하면 전체 메모리를 차지하므로 결과 없이 스크립트가 실행됩니다. 메모리를 차지하지 않도록 스크립트를 수정하고 싶습니다. 어떤 모듈도 사용하고 싶지 않습니다. 한 번에 하나의 파일만 메모리에 로드하면 메모리가 절약되지만 그렇게 할 수는 없다고 생각합니다. 내 스크립트를 수정하는 데 도움을 주세요.

답변1

시도해 보셨나요 awk? 대용량 파일을 더 잘 처리할 수 있을지는 확실하지 않지만 perl시도해 볼 가치가 있습니다.

awk 스크립트 내부:

BEGIN {
    RS=">[0-9]+"
}

FNR==1{next}

NR==FNR {
    a[$1]++
    next
}


$1 in a {
    b[$1]++
    next
}

{
    c[$1]++
}

END {
    for (key in a) {
        if (b[key] == "") {
            printf key"\tfile1:"a[key]"\t\tcount:"a[key]"\n"
        } else {
            printf key"\tfile1:"a[key]"\tfile2:"b[key]"\tcount:"a[key]+b[key]"\n"
        }
    }
    for (key in c) {
        printf key"\t\tfile2:"c[key]"\tcount:"c[key]"\n"
    }
}

실행하려면:

$ awk -f myscript.awk file1 file2 > output.txt

다음을 사용하여 테스트했습니다.

파일1

>1
ATGCCGTT      file1:1
+
HHHHKKKK

>2
ATTCCAACg        file2:1
+
=#GJLMNB

파일2

>2
ATGCCGTT       file2:3
+
JJKHHTTT

>3
ATTCCAAC        file2:1
+
=#GJLMNB

터미널 출력:

ATTCCAACg   file1:1         count:1
ATGCCGTT    file1:1 file2:1 count:2
ATTCCAAC            file2:1 count:1

답변2

프로그램에 신비한 주문을 추가하세요

use DB_File;
my %seen; 
unlink '/tmp/translation.db';
sleep 2; 
tie ( %seen, 'DB_File', '/tmp/translation.db' )
    or die "Can't open /tmp/translation.db\n";

해시는 더 이상 메모리에 상주하지 않고 디스크의 데이터베이스에 상주하게 됩니다. 나머지 코드는 그대로 둘 수 있습니다. 사실, DB_File 모듈을 사용했지만 사용하지 않을 이유가 전혀 없습니다. 그것은 모든 것과 함께 제공됩니다즉시 설치가 가능하므로 따로 설치할 필요가 없습니다.

내 해시가 매우 커지고 흐릿하게 정의된 거대 지점을 통과한 후 작업 속도가 상당히 빨라지는 경우 항상 이 접근 방식을 사용합니다.

관련 정보