解析sdf文件,性能问题

时间:2013-04-02 13:15:26

标签: python performance sdf

我有一个脚本,它读取不同的文件并在大型sdf数据库中搜索分子ID(每个大约4.0 GB)。

这个脚本的想法是将每个分子从我的原始数据库中的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()

它完美地运作,但它非常慢......对于我需要的东西来说太慢了。有没有办法以减少计算时间的方式重写此脚本?

非常感谢你。

2 个答案:

答案 0 :(得分:1)

主要问题是你有三个嵌套循环:分子文档,分子和文本解析在内循环。那味道很麻烦 - 我的意思是,quadratic complexity。你应该移动大量文件解析内部循环之外,并使用集合或字典分析。 像这样:

  1. 对于每个sdf文件
  2. 对于每一行,如果是分子定义
  3. 检查无法分子的词典
  4. 如果存在,处理它并从字典中删除未发现的分子
  5. 这样,您将对每个sdf文件进行一次解析,并且对于每个找到的分子,速度将进一步提高。

答案 1 :(得分:0)

past_mol成为一个集合,而不是列表。那会加快

filine[i][0:-1] not in past_mol

因为检查集合中的成员资格是O(1),所以检查列表中的成员资格是O(n)。


尽量不要一次写入一行文件。相反,在列表中保存行,将它们连接成一个字符串,然后将一次调用写入filout.write


通常最好不要允许函数修改全局变量。 sdf_grep修改全局变量past_mol

past_mol添加到sdf_grep的参数中,您明确指出sdf_grep取决于past_mol的存在(否则,sdf_grep并非如此一个独立的功能)。

如果将past_mol作为第三个参数传递给sdf_grep,那么Python将创建一个名为past_mol的新局部变量,该变量将指向与全局变量{{相同的对象1}}。由于该对象是一个集合而一个集合是一个可变对象,past_mol也会影响全局变量past_mol.add(sline)

作为一个额外的好处,Python比全局变量更快地查找局部变量:

past_mol

如果你使用一个变量(让我们称之为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 )来跟踪我们是否在我们想要保留的行块之内,可以大大简化

sdf_grep。 (“行数”是指以found开头,以molname结尾的行:

"$$$$"