首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >解析sdf文件,性能问题

解析sdf文件,性能问题
EN

Stack Overflow用户
提问于 2013-04-02 21:15:26
回答 2查看 2.7K关注 0票数 0

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

这个脚本的思想是将id列表(大约287212个分子)中的每个分子从我的原始数据库复制到一个新的数据库中,每个分子只有一个拷贝(在本例中,是遇到的第一个拷贝)。

我写了这个脚本:

代码语言:javascript
复制
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()

它工作得很完美,但速度非常慢……对我需要的来说太慢了。有没有办法以一种可以减少计算时间的方式重写这个脚本?

非常感谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-04-02 21:48:58

主要问题是你有三个嵌套的循环:分子文档,分子和内部循环中的文件解析。这闻起来像是麻烦,我是说,quadratic complexity。您应该将解析的大型文件移到内部循环之外,并为分子使用set或字典。如下所示:

对于每个sdf文件和每行,如果其为 definition

  1. Check in
    1. of
    2. ,则对其进行处理并从未找到分子的字典中删除

这样,您将只解析每个sdf文件一次,并且对于找到的每个分子,速度将进一步提高。

票数 1
EN

Stack Overflow用户

发布于 2013-04-02 21:26:34

past_mol成为一个集合,而不是一个列表。这将加快速度

代码语言:javascript
复制
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查找局部变量的速度比查找全局变量的速度更快:

代码语言:javascript
复制
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开头、以"$$$$"结尾的行块):

代码语言:javascript
复制
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()
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15765112

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档