[英]Improve the speed of for loop for readline of very big files
我正在尝试提高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()
f2
文件的0到100行之间匹配(str(line2[5])=="CG") and (str(line2[2])=="+")
过滤器。
您在文件I / O上有一个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))
构建完该字典后,您可以在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
文件中存储整行,当然也不BS_Forward.fastq_bismark_pe.CX_report.txt
存储为Python 可打印的表示形式 。 我不知道您打算如何使用这些数据,但至少考虑使用JSON将lt
列表序列化为字符串表示形式。 JSON可被其他平台读取,并且可以更快地解析回合适的Python数据结构。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.