Подсчет подпоследовательностей в сотнях ГБ данных
Я пытаюсь обработать очень большой файл и подсчитать частоту всех последовательностей определенной длины в файле.
Чтобы проиллюстрировать, что я делаю, рассмотрим небольшой входной файл, содержащий последовательностьabcdefabcgbacbdebdbbcaebfebfebfeb
Ниже код считывает весь файл и получает первую подстроку длины n (ниже я установил это значение на 5, хотя я хочу иметь возможность изменить это) и подсчитывает его частоту:
abcde => 1
Следующая строка перемещает один символ вправо и делает то же самое:
bcdef => 1
Затем он продолжается для остальной части строки и печатает 5 наиболее часто встречающихся последовательностей:
open my $in, '<', 'in.txt' or die $!; # 'abcdefabcgbacbdebdbbcaebfebfebfeb'
my $seq = <$in>; # read whole file into string
my $len = length($seq);
my $seq_length = 5; # set k-mer length
my %data;
for (my $i = 0; $i <= $len - $seq_length; $i++) {
my $kmer = substr($seq, $i, $seq_length);
$data{$kmer}++;
}
# print the hash, showing only the 5 most frequent k-mers
my $count = 0;
foreach my $kmer (sort { $data{$b} <=> $data{$a} } keys %data ){
print "$kmer $data{$kmer}\n";
$count++;
last if $count >= 5;
}
ebfeb 3
febfe 2
bfebf 2
bcaeb 1
abcgb 1
Однако я хотел бы найти более эффективный способ достижения этого. Если входной файл был 10 ГБ или 1000 ГБ, тогда чтение всего этого в строку было бы очень дорогостоящим.
Я думал о чтении по блокам символов, скажем, по 100 за раз, и продолжал, как описано выше, но здесь последовательности, охватывающие 2 блока, не будут правильно подсчитаны.
Моя идея тогда состоит в том, чтобы читать только n символов из строки, а затем переходить к следующему n символам и делать то же самое, подсчитывая их частоту в хэше, как указано выше.
Есть какие-нибудь предложения о том, как я мог это сделать? Я посмотрелчитать используя смещение, но не могу понять, как я могу включить это здесьЯвляетсяsubstr
самый эффективный инструмент памяти для этой задачи?