我写了一个脚本,它读取不同的文件,并在大型sdf数据库(每个约4.0 GB )中搜索分子ID。
这个脚本的思想是将id列表(大约287212个分子)中的每个分子从我的原始数据库复制到一个新的数据库中,每个分子只有一个拷贝(在本例中,是遇到的第一个拷贝)。
我写了这个脚本:
import re
import sys
import os
def sdf_grep (molname,files):
filin = open(files, 'r')
filine= filin.readlines()
for i in range(0,len(filine)):
if filine[i][0:-1] == molname and filine[i][0:-1] not in past_mol:
past_mol.append(filine[i][0:-1])
iterate = 1
while iterate == 1:
if filine[i] == "$$$$\n":
filout.write(filine[i])
iterate = 0
break
else:
filout.write(filine[i])
i = i+1
else:
continue
filin.close()
mol_dock = os.listdir("test")
listmol = []
past_mol = []
imp_listmol = open("consensus_sorted_surflex.txt", 'r')
filout = open('test_ini.sdf','wa')
for line in imp_listmol:
listmol.append(line.split('\t')[0])
print 'list ready... reading files'
imp_listmol.close()
for f in mol_dock:
print 'reading '+f
for molecule in listmol:
if molecule not in past_mol:
sdf_grep(molecule , 'test/'+f)
print len(past_mol)
filout.close()它工作得很完美,但速度非常慢……对我需要的来说太慢了。有没有办法以一种可以减少计算时间的方式重写这个脚本?
非常感谢。
发布于 2013-04-02 21:48:58
主要问题是你有三个嵌套的循环:分子文档,分子和内部循环中的文件解析。这闻起来像是麻烦,我是说,quadratic complexity。您应该将解析的大型文件移到内部循环之外,并为分子使用set或字典。如下所示:
对于每个sdf文件和每行,如果其为 definition
这样,您将只解析每个sdf文件一次,并且对于找到的每个分子,速度将进一步提高。
发布于 2013-04-02 21:26:34
让past_mol成为一个集合,而不是一个列表。这将加快速度
filine[i][0:-1] not in past_mol由于检查集合中的成员关系是O(1),而检查列表中的成员关系是O(n)。
尽量不要一次只写一行。相反,将行保存在列表中,将它们连接到单个字符串中,然后使用one call to filout.write将其写出来。
通常,最好不允许函数修改全局变量。sdf_grep修改全局变量past_mol。
通过将past_mol添加到sdf_grep的参数中,您可以明确地表明sdf_grep依赖于past_mol的存在(否则,sdf_grep实际上不是一个独立的函数)。
如果您将past_mol作为第三个参数传递给sdf_grep,那么Python将创建一个名为past_mol的新局部变量,该变量将指向与全局变量past_mol相同的对象。由于该对象是一个集合,而集合又是一个可变对象,因此past_mol.add(sline)也会影响全局变量past_mol。
此外,Python查找局部变量的速度比查找全局变量的速度更快:
def using_local():
x = set()
for i in range(10**6):
x
y = set
def using_global():
for i in range(10**6):
y
In [5]: %timeit using_local()
10 loops, best of 3: 33.1 ms per loop
In [6]: %timeit using_global()
10 loops, best of 3: 41 ms per loop如果您使用一个变量(让我们称其为found)来跟踪我们是否在我们想要保留的行块中,那么sdf_grep可以大大简化。(这里所说的“行块”是指以molname开头、以"$$$$"结尾的行块):
import re
import sys
import os
def sdf_grep(molname, files, past_mol):
chunk = []
found = False
with open(files, 'r') as filin:
for line in filin:
sline = line.rstrip()
if sline == molname and sline not in past_mol:
found = True
past_mol.add(sline)
elif sline == '$$$$':
chunk.append(line)
found = False
if found:
chunk.append(line)
return '\n'.join(chunk)
def main():
past_mol = set()
with open("consensus_sorted_surflex.txt", 'r') as imp_listmol:
listmol = [line.split('\t')[0] for line in imp_listmol]
print 'list ready... reading files'
with open('test_ini.sdf', 'wa') as filout:
for f in os.listdir("test"):
print 'reading ' + f
for molecule in listmol:
if molecule not in past_mol:
filout.write(sdf_grep(molecule, os.path.join('test/', f), past_mol))
print len(past_mol)
if __name__ == '__main__':
main()https://stackoverflow.com/questions/15765112
复制相似问题