簡體   English   中英

計算時間瘋狂地長在python中

[英]Computation time insanely long in python

我正在運行我的代碼,包括查找平均值。 在~600萬行CSV(ssm_resnik.txt)中,第一行是一個引用,第二行是另一行,第三行是2個引用之間的“距離”。 這些距離由生物標准任意定義,對此問題不重要。 大多數參考文獻將與大多數參考文獻相對應,因此具有超過6百萬行的巨大CSV。 在另一個CSV(all_spot_uniprot.txt)中,我有~3600個點(第一列),每個點都有一個或多個引用(第三列)。 這些值與巨大的CSV相同。 我需要將第二個文件的3600個spot ref中的每一個與同一個文件中的所有其他3600-1 ref進行比較。 所有可能的組合(如果存在)都位於第一個巨大的CSV文件(ssm_resnik.txt)中。 對於all_spot_uniprot.txt,每個2 spot ref將作為對應引用的迭代器(在第三列中),並將迭代巨大的CSV文件,如果存在,則顯示兩個“VS”引用的值。

我的代碼有什么問題? 那么......每次迭代10秒,3600 * 3600 * 10 = 129.600.000秒= 1500天(差不多5年)。 這發生在我的核心i3中,但在mac中。 下面是我的代碼和每個文件的一部分。 請指教。 有任何代碼設計缺陷嗎? 有一些方法可以減少計算時間嗎? 提前致謝...

import csv

spot_to_uniprot=open('all_spot_uniprot.txt', 'rbU')
STU=csv.reader(spot_to_uniprot, delimiter='\t')

uniprot_vs_uniprot=open('ssm_resnik.txt', 'rbU')
allVSall= csv.reader(uniprot_vs_uniprot, delimiter='\t')

recorder=open('tabela_final.csv', 'wb')
fout=csv.writer(recorder, delimiter='\t', quotechar='"')

dict_STU={} #dicionário 'spot to uniprot'
dict_corresp={} #for each pair of uniprot ref as key and as value
#a list of lists with the first list as one spot and the second list is the spot+1
dict_corresp_media={}##average of one spot to other
total_correspondencias_x_y=[]
_lista_spot=[]
lista_spot=[]
lista_temp=[]
lista_CSV=[]

for a in STU:
    _lista_spot.append(int(a[0]))
    if a[0] not in dict_STU.keys():
        dict_STU[a[0]]=[]
        dict_STU[a[0]].append(a[2])
    else:        
        dict_STU[a[0]].append(a[2])
n_spot=max(_lista_spot)

spot_to_uniprot.close()

##for aa in _lista_spot:
##    lista_spot.append(int(aa))
##lista_spot.sort()

for i in allVSall:
    lista_CSV.append(i)
tuple_CSV=tuple(lista_CSV)

uniprot_vs_uniprot.close()

for h in range(1, n_spot):
    for _h in range(h+1, n_spot+1):
        #print h, 'h da lista_spot'
        del total_correspondencias_x_y[:]
        total_correspondencias_x_y.append(dict_STU[str(h)])
        #print h, 'h'
        #print _h, '_h'
        #print __h, '__h'
        total_correspondencias_x_y.append(dict_STU[str(_h)])
        print total_correspondencias_x_y, 'total_corresp_x_y'

        for c1 in total_correspondencias_x_y[0]:
            if c1=='No Data':
                pass
            else:
                for c2 in total_correspondencias_x_y[1]:
                    if c2=='No Data':
                        pass
                    else:
                        #print c1, c2, 'c1 e c2'
                        for c3 in lista_CSV:
                            if c1 in c3[0]:
                                if c2 in c3[1]:
                                    lista_temp.append(c3[2])
                                    print lista_temp, 'lista_temp'

        elements=len(lista_temp)
        if len(lista_temp)==0:
            dict_corresp_media[str(h)+'_'+str(_h)]=0
        else:
            temp_d=0
            for d in lista_temp:
                temp_d +=float(d)
            media_spots=temp_d/elements
            dict_corresp_media[str(h)+'_'+str(_h)]=media_spots

        print dict_corresp_media[str(h)+'_'+str(_h)]
        lista_temp=[]

recorder.close()

這是我文件的一部分:

all_spot_uniprot.txt

1   spr0001 Q8DRQ4
1   SP0001  O08397
1   SPN01072    B5E568
2   spr0002 P59651
2   SP0002  O06672
2   SPN01074    B5E569
3   spr0005 Q8DRQ2
3   SP0005  Q97TD1
3   SPN01078    B5E572
4   spr0006 Q8DRQ1
4   SP0006  Q97TD0
4   SPN01079    B5E573
5   spr0009 Q8DRQ0
5   SP0009  Q97TC7
6   spr0010 Q8DRP9
6   SP0011  Q97TC5
6   SPN01085    B5E578
7   spr0012 P59652
7   SP0013  O69076
7   SPN01087    B5E580
8   spr0017 Q8DRP6
8   SP0017  No Data
8   SPN01090    B5E5G4
9   spr0020 Q8CZD0
9   SP0018  Q97TC2
9   SPN01093    B5E5G7
10  spr0021 P65888
10  SP0019  P65887
..  ......  ......  ......
..  ......  ......  ......
3617    spr2016 Q8DMY7
3617    spr0324 Q8DR62
3617    SP2211  No Data
3617    SP1311  No Data
3617    SP1441  No Data
3617    SPN11022    No Data
3617    SPN01038    No Data
3617    SPN08246    No Data
3618    spr2018 Q8DMY5
3618    SP0812  No Data
3618    SP2213  No Data
3618    SPN04196    B5E3J0
3618    SPN01040    B5E3V9
3619    spr2040 Q8DMW6
3619    SP2234  Q97N38
3619    SPN01065    B5E462
3620    spr2043 P60243

ssm_resnik.txt

Q8DRQ4  O08397  1.0
Q8DRQ4  B5E568  1.0
Q8DRQ4  P59651  0.12077157944440875
Q8DRQ4  O06672  0.12077157944440875
Q8DRQ4  B5E569  0.12077157944440875
Q8DRQ4  Q8DRQ1  0.12077157944440875
Q8DRQ4  Q97TD0  0.12077157944440875
Q8DRQ4  B5E573  0.12077157944440875
Q8DRQ4  Q8DRP9  0.07139907404780385
Q8DRQ4  Q97TC5  0.07139907404780385
Q8DRQ4  B5E578  0.07139907404780385
Q8DRQ4  P59652  0.04789965413510797
Q8DRQ4  O69076  0.04789965413510797
Q8DRQ4  B5E580  0.04698170092888175
Q8DRQ4  Q8DRP6  0.12077157944440875
Q8DRQ4  P65888  0.05619465373456477
Q8DRQ4  P65887  0.05619465373456477
Q8DRQ4  B5E5G8  0.05619465373456477
Q8DRQ4  Q8DRP3  0.0115283466875553
Q8DRQ4  Q97TC0  0.0115283466875553
Q8DRQ4  B5E5G9  0.0115283466875553
Q8DRQ4  Q8DRP2  0.05619465373456477
Q8DRQ4  Q97TB9  0.05619465373456477
Q8DRQ4  B5E5H1  0.05619465373456477
Q8DRQ4  Q8DRP0  0.12077157944440875
Q8DRQ4  B5E5H3  0.12077157944440875
Q8DRQ4  Q8DNI4  0.12077157944440875
Q8DRQ4  Q8CWP0  0.12077157944440875
Q8DRQ4  Q97CV3  0.12077157944440875
Q8DRQ4  Q97P52  0.12077157944440875
O08397  Q97PH8  0.12077157944440875
O08397  P59200  0.10979991157849654
O08397  P59199  0.10979991157849654
O08397  B5E5I1  0.12077157944440875
O08397  Q8DRN5  0.047725405544042546
O08397  Q97TA8  0.047725405544042546
O08397  B5E5I4  0.047725405544042546
O08397  Q8DRN4  0.1555714706579846
O08397  Q97TA7  0.1555714706579846
O08397  B5E5I5  0.1555714706579846
O08397  Q97TA6  0.02938784938305615
O08397  Q8DRN2  0.02938784938305615
O08397  Q9F7T4  0.02938784938305615
O08397  P59653  0.04191624792292713
O08397  Q03727  0.04191624792292713
O08397  B5E5J1  0.045754049904644475
O08397  P59654  0.01167129073292015
O08397  P36498  0.01167129073292015
O08397  B5E5J2  0.0
O08397  Q8DRM7  0.05619465373456477
O08397  Q07296  0.05619465373456477
O08397  B5E5J3  0.05619465373456477
O08397  Q97TA3  0.05619465373456477
O08397  B5E5J5  0.05619465373456477
O08397  Q97T99  0.05619465373456477
O08397  Q8DRL9  0.05619465373456477
O08397  Q97T96  0.05619465373456477
O08397  B5E5K1  0.05619465373456477
O08397  Q97T95  0.05619465373456477
O08397  Q8DRL7  0.05619465373456477

600萬行可以保存在內存中或SQLite數據庫中。 把它放在那里並利用提供的查找優化:

with open('ssm_resnik.txt', 'rbU') as uniprot_vs_uniprot:
    reader = csv.reader(uniprot_vs_uniprot, delimiter='\t')
    allVSall = { tuple(r[:2]): float(r[2]) for r in reader }

現在allVSall是一個提供O(1)查找的映射; 這樣可以節省您為每個組合生成的600萬行的循環。 這節省了很多循環。

在閱讀all_spot_uniprot列表時,使用collections.defaultdict更容易:

from collections import defaultdict

dict_STU = defaultdict(list)
with open('all_spot_uniprot.txt', 'rbU') as spot_to_uniprot:
    reader = csv.reader(spot_to_uniprot, delimiter='\t')
    for row in reader:
        dict_STU[int(row[0])].append(row[2])

這里不需要找到max ,只需列出鍵並將它們傳遞給itertools.permutationsitertools.product函數以生成組合。

以下代碼以更緊湊的形式復制您的操作,使用更少的列表,並使用O(1)字典查找更少的循環:

from itertools import permutations, product, ifilter

no_no_data = lambda v: v != 'No Data'
dict_corresp_media = {}

for a, b in permutations(dict_STU.iterkeys(), r=2):
    # retrieve the a and b lists of possible keys, for which we need to loop over their products
    # we filter each for the `No Data` keys
    aval, bval = ifilter(no_no_data, dict_STU[a]), ifilter(no_no_data, dict_STU[b])

    matches = [allVSall[c1, c2] for c1, c2 in product(aval, bval) if (c1, c2) in allVSall]
    dict_corresp_media['{}_{}'.format(a, b)] = sum(matches) / len(matches) if matches else 0

對於您的輸入樣本,它會在幾分之一秒內吐出:

>>> pprint.pprint(dict_corresp_media)
{'10_1': 0,
 '10_2': 0,
 '10_3': 0,
 '10_4': 0,
 '10_5': 0,
 '10_6': 0,
 '10_7': 0,
 '10_8': 0,
 '10_9': 0,
 '1_10': 0.05619465373456477,
 '1_2': 0.12077157944440875,
 '1_3': 0,
 '1_4': 0.12077157944440875,
 '1_5': 0,
 '1_6': 0.07139907404780385,
 '1_7': 0.04759366973303256,
 '1_8': 0.12077157944440875,
 '1_9': 0,
 '2_1': 0,
 '2_10': 0,
 '2_3': 0,
 '2_4': 0,
 '2_5': 0,
 '2_6': 0,
 '2_7': 0,
 '2_8': 0,
 '2_9': 0,
 '3_1': 0,
 '3_10': 0,
 '3_2': 0,
 '3_4': 0,
 '3_5': 0,
 '3_6': 0,
 '3_7': 0,
 '3_8': 0,
 '3_9': 0,
 '4_1': 0,
 '4_10': 0,
 '4_2': 0,
 '4_3': 0,
 '4_5': 0,
 '4_6': 0,
 '4_7': 0,
 '4_8': 0,
 '4_9': 0,
 '5_1': 0,
 '5_10': 0,
 '5_2': 0,
 '5_3': 0,
 '5_4': 0,
 '5_6': 0,
 '5_7': 0,
 '5_8': 0,
 '5_9': 0,
 '6_1': 0,
 '6_10': 0,
 '6_2': 0,
 '6_3': 0,
 '6_4': 0,
 '6_5': 0,
 '6_7': 0,
 '6_8': 0,
 '6_9': 0,
 '7_1': 0,
 '7_10': 0,
 '7_2': 0,
 '7_3': 0,
 '7_4': 0,
 '7_5': 0,
 '7_6': 0,
 '7_8': 0,
 '7_9': 0,
 '8_1': 0,
 '8_10': 0,
 '8_2': 0,
 '8_3': 0,
 '8_4': 0,
 '8_5': 0,
 '8_6': 0,
 '8_7': 0,
 '8_9': 0,
 '9_1': 0,
 '9_10': 0,
 '9_2': 0,
 '9_3': 0,
 '9_4': 0,
 '9_5': 0,
 '9_6': 0,
 '9_7': 0,
 '9_8': 0}

當腳本花費很長時間我會:

python -m cProfile myscript.py

我在一段時間后停止腳本。 輸出總結了在任何功能和模塊中花費的時間。 如果數字越大,問題就在於此。

查看其他分析方法: 如何分析python腳本?

此外,像評論建議您也可以考慮使用專用數據庫。

看起來您的程序的復雜性遠遠高於您的問題的復雜性。 使用像cProfile或PyPy這樣的東西(或者甚至在C中重新實現)將幫助你加速部分程序,但不會解決基本問題 - 嵌套for循環。

看看你是否可以以更平坦的方式重寫算法。 請記住,這是Python和flat is better than nested

如果您的代碼具有差的漸近復雜性,那么沒有優化會有所幫助。 想想你是否可以簡化你的問題。 例如,你真的需要檢查所有N * N對嗎? 也許你可以提前丟棄一些套裝?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM