提高超大文件的readline的for循环速度

时间:2019-02-02 18:14:33

标签: python python-3.x for-loop if-statement

我正在尝试提高for循环从超大文件中读取行的速度。我有两个文件,我在NVARCHAR(MAX)循环中逐行从第一个文件中获取信息,并通过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过滤器匹配。

1 个答案:

答案 0 :(得分:2)

您具有O(N * M)比文件环I / O,这是非常慢确实。您可以通过使用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))

构建完该字典后,您可以在O(1)时间内针对s0查找匹配项,因此您在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 printable representation。我不知道你打算如何使用这些数据,但至少可以考虑使用JSON以连载的lt列表为字符串表示。 JSON可以被其他平台读取,并且可以更快地解析回合适的Python数据结构。