Улучшена скорость цикла for readline для очень больших файлов - PullRequest
0 голосов
/ 02 февраля 2019

Я пытаюсь улучшить скорость цикла for для чтения строк из очень больших файлов.У меня есть два файла, я беру информацию из первого файла построчно в цикле for и сопоставляю их каждый со строками из второго файла с помощью оператора if.Поскольку оба файла содержат миллионы строк, это занимает слишком много времени.

Я публикую здесь свой код;Как улучшить оператор цикла для увеличения скорости выполнения?

#!/usr/bin/python

#open file1
f1 = open("../../Reapeat_analysis/FIMO/fimo_out/fimo.gff",'r')
#open file2
f2 = open("../BS_Forward.fastq_bismark_pe.CX_report.txt",'r')

f1.seek(0)
f2.seek(0)

#open and save output
fOut = open("output_sample_CG+.txt",'w')

#Reading file1 lines in for loop
for line1 in f1:
    line1 = line1.split('\t')
    s1 = int(line1[3])
    s2 = int(line1[4])
    s0 = str(line1[0])
    count = 0
    percent = 0
    lt = []

    #Reading file2 lines for each file1 line
    for line2 in f2:
        line2 = line2.split("\t")

        #Matching desired condition
        if (s0 == str(line2[0])) and (s1 <= int(line2[1]) <= s2) and (str(line2[5])=="CG") and (str(line2[2])=="+"):
            lt.append(line2)
            count = count + 1

    #saving each matched conditions
    fOut.write(str(s1) + "-" + str(s2) + ":" + str(s0) + "\t" + str(count) + "\t" + str(lt))
    f2.seek(0)
fOut.close()

От 0 до 100 строк файла f2 соответствуют фильтру (str(line2[5])=="CG") and (str(line2[2])=="+").

1 Ответ

0 голосов
/ 02 февраля 2019

У вас есть O (N * M) цикл по файловому вводу / выводу, который действительно очень медленный.Вы можете улучшить обработку по каждой строке, используя модуль csv, чтобы выполнить синтаксический анализ каждой строки в списке для вас в коде C и отбросить избыточные вызовы str() (у вас уже есть строки), но ваша настоящая проблема - вложеннаяпетля.

Вы можете легко избежать этой петли.Во втором файле может быть миллионы строк, но вы уже фильтруете эти строки до намного меньшего числа, от 0 до 100. Это можно легко хранить в памяти и получить доступ к значению s0 в следующемнет времени.

Сохранять информацию из каждой строки в словаре;предварительно проанализируйте целое число во втором столбце и сохраните всю строку для вывода в выходной файл в списке lt:

import csv

# dictionary mapping row[0] to a list of (int(row[1]), line) values
report_map = {}

with open("../BS_Forward.fastq_bismark_pe.CX_report.txt", 'r', newline='') as report:
    reader = csv.reader(report, delimiter='\t')
    for row in reader:
        if row[2] != "+" or row[5] != "CG":
            continue
        key, value = row[0], int(row[1])
        line = '\t'.join(row)
        report_map.setdefault(key, []).append((value, line))

После построения этого словаря вы можете искать совпадения с s0 вO (1) раз, так что ваш цикл над f1 является простым циклом с дешевой операцией для каждой строки.Когда вы находите совпадение в словаре report_map, вам нужно только зациклить связанный список, чтобы отфильтровать по целочисленным значениям row[1]:

with open("../../Reapeat_analysis/FIMO/fimo_out/fimo.gff", 'r', newline='') as fimo, \
     open("output_sample_CG+.txt", 'w', newline='') as fout:
    reader = csv.reader(fimo, delimiter='\t')
    writer = csv.writer(fout, delimeter='\t')
    for row in reader:
        s0 = row[0]
        s1, s2 = map(int, row[3:5])
        if s0 not in report_map:
            continue
        lt = [r for i, r in report_map[s0] if s1 <= i <= s2]
        writer.writerow(["{}-{}:{}".format(s1, s2, s0), len(lt), str(lt)])

Я настоятельно рекомендую против хранение всей строки из файла BS_Forward.fastq_bismark_pe.CX_report.txt, конечно, не в виде печатаемого представления Python .Я не знаю, как вы планируете использовать эти данные, но, по крайней мере, рассмотрите возможность использования JSON для сериализации списка lt в строковое представление.JSON может быть прочитан другими платформами и быстрее разбирается в подходящую структуру данных Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...