Эффективные методы буферизации и сканирования больших файлов на Python

Описание проблемы, с которой я столкнулся, немного сложнее, и я ошибусь, если предоставлю более полную информацию. Для нетерпеливых вот самый краткий способ резюмировать его:

Что является самым быстрым (наименьшее выполнение время) способ разбить текстовый файл на ВСЕ (перекрывающиеся) подстроки размера N (связанные N, например 36) при отбрасывании символов новой строки.

Я пишу модуль, который анализирует файлы в формате генома на основе FASTA ascii. Эти файлы содержат так называемый эталонный геном человека 'hg18', который вы можете загрузить из браузера генома UCSC (идите, пули!), Если хотите.

Как вы заметите, файлы генома состоят из chr [1..22] .fa и chr [XY] .fa, а также из набора других небольших файлов, которые не используются в этом модуле.

Уже существует несколько модулей для анализа файлов FASTA, например как SeqIO от BioPython. (Извините, я бы разместил ссылку, но у меня пока нет для этого возможностей.) К сожалению, каждый модуль, который мне удалось найти, не выполняет ту конкретную операцию, которую я пытаюсь выполнить.

Моему модулю необходимо разделить данные генома ('CAGTACGTCAGACTATACGGAGCTA' может быть строкой, например) в каждую перекрывающуюся подстроку длиной N. Позвольте мне привести пример с использованием очень маленького файла (фактические файлы хромосом имеют длину от 355 до 20 миллионов символов) и N = 8

>>>import cStringIO
>>>example_file = cStringIO.StringIO("""\
>header
CAGTcag
TFgcACF
""")
>>>for read in parse(example_file):
...    print read
...
CAGTCAGTF
AGTCAGTFG
GTCAGTFGC
TCAGTFGCA
CAGTFGCAC
AGTFGCACF

Функция, которую я обнаружил, имела абсолютную лучшую производительность среди методов, которые я мог придумать, это следующая :


def parse(file):
  size = 8 # of course in my code this is a function argument
  file.readline() # skip past the header
  buffer = ''
  for line in file:
    buffer += line.rstrip().upper()
    while len(buffer) >= size:
      yield buffer[:size]
      buffer = buffer[1:]

Это работает, но, к сожалению, все еще требуется около 1,5 часов (см. Примечание ниже), чтобы таким образом проанализировать геном человека. Возможно, это лучшее, что я собираюсь увидеть с помощью этого метода (полный рефакторинг кода может быть в порядке, но я бы хотел избежать этого, поскольку этот подход имеет некоторые очень специфические преимущества в других областях кода), но я подумал, что передам это сообществу.

Спасибо!

  • Обратите внимание, на этот раз много дополнительных вычислений, такие как вычисление чтения противоположной цепочки и выполнение поиска по хеш-таблице для хэша размером примерно 5G.

Заключение после ответа: Оказывается, использование fileobj.read () и последующее изменение результирующей строки (string. replace () и т. д.) занимал относительно мало времени и памяти по сравнению с остальной частью программы, поэтому я использовал этот подход. Спасибо всем!

9
задан eblume 11 March 2011 в 14:06
поделиться