如何在Python中优化庞大列表的笛卡尔积代码

0 投票
2 回答
511 浏览
提问于 2025-04-18 13:23

我才编程几个月,但我做了一些研究,尝试了这段代码。

我现在有两个文件。第一个文件里有大约300万个蛋白质ID(字符串)。第二个文件是每个蛋白质的编号列表,每个特征都有一个独特的编号:比如,如果蛋白质A有3个特征,它会显示为proteinA_1、proteinA_2、proteinA_3。有些蛋白质可能有多达3000个特征。

我想要一份特征交互对的列表。

到目前为止我的代码是这样的:

import csv,itertools, gzip
from collections import Counter
#opens and reads/writes files using csv and gzip   

#1. Counts how many features each protein has in the second file.
cnt = Counter()                     
for row in cfile1:                  
    cnt[row[0]]+=1  

#2. Considers pairs of interacting proteins
for row in cfile2:
    p1 = row[0]; p2=row[1]          

    #3.1. if both proteins have no features, just write the pair to the new file    
    if cnt[p1]==0 and cnt[p2]==0:   
        cout.writerow([p1,p2])

    #3.2. if one protein has no feature, but the other has a feature write e.g. (p1_1,p2) (p1_2,p2) (p1_3,p2)... (p1_k,p2)
    elif cnt[p1]!=0 and cnt[p2]==0: 
        x = cnt[p1]                 
        for i in range(1,x+1):
            p1n=p1+"_%d"%(i)
            cout.writerow([p1n,p2])

    elif cnt[p1]==0 and cnt[p2]!=0:
        x = cnt[p2]
        for i in range(1,x+1):
            p2n=p2+"_%d"%(i)
            cout.writerow([p1,p2n])

    #3.3 if both proteins have features, create a list of the enumerated proteins then get the cartesian product of that list, so that you get all possible f-f interactions
    elif (cnt[p1]!=0) and (cnt[p2]!=0): 
        x = cnt[p1];y = cnt[p2]             
        xprots = []; yprots=[]
        for i in range(1,x+1):
            p1n =p1+"_%d"%(i)
            xprots.append(p1n)
        for i in range(1,y+1):
            p2n=p2+"_%d"%(i)
            yprots.append(p2n)
        for i in itertools.product(xprots,yprots):
            cout.writerow([i[0],i[1]])      

这段代码似乎运行得不错,但处理前15万个对花了大约18个小时。目前输出文件里几乎有20亿个交互。

有没有其他方法可以加快这个速度,除了可能减少一些特征?任何建议都非常感谢!

提前谢谢你们!

2 个回答

0

我觉得在Python代码优化方面的空间不大。可以建议你尝试用C或C++写一个扩展,这样可以大幅提升计算性能。

编写Python扩展的过程有很多文档说明,实际上对于需要大量计算的应用效果很好。

关于这个问题的文档网站是: https://docs.python.org/2/extending/

希望对你有帮助!

0

听起来你遇到的问题是因为你正在做的事情本身就很复杂,即使是最快、最优化的低级C程序也需要花费非常长的时间。

处理前150000对数据大约花了18个小时。目前输出文件中几乎有20亿个交互。

我们来看看这些数字。你说有300万个蛋白质对,每个蛋白质最多可以有3000个特征。那么输出的总行数大约是(300万)*(3000的平方),也就是270万亿行。看起来每行至少会包含10个字符(字节),所以我们在说的输出大约是270太字节。

我怀疑你的硬盘连存下这么大的文件都不够。你需要重新考虑一下你要做的事情;即使你的代码提升了1000倍,输出的大小也不会改变,而你的程序速度也不能快于它所产生的数据量。如果你真的需要这么多输出,可能更适合用超级计算机或集群进行并行计算,这样会需要根据架构进行专业的编程。

撰写回答