2012-12-03 16 views
1

我試圖提高一個函數的性能,該函數計算Python中2D數組的列中某個元素的出現次數。時間來自cProfile,它也告訴我count()每357595次呼叫只需要〜.08s。從Python中的二維數組中選擇列的最快方法?

for循環是最快的(爲357595個呼叫.375s):

def count_column(grid, j, element): 
    count = 0 
    for x in range(0, len(grid)): 
     if grid[x][j] == element: 
      count += 1 
    return count 

列表解析是由可忽略的量更慢(.400s爲357595個呼叫):

def count_column(grid, j, element): 
    return [x[j] for x in grid].count(element) 

郵編是最慢的一個巨大的餘地(對於357595電話.741s):

def validate_column(grid, j, element): 
    return zip(*grid)[j].count(element) 

有沒有更快的方法來做到這一點,或最好的方法是用chain.from_iterable來平坦化陣列?

+7

你有沒有考慮過使用'numpy'? –

+0

在任何其他情況下,我完全可以,但是我必須運行該腳本的計算機沒有它,我也沒有被允許安裝它。 – xjtian

+0

這是Python 2還是3? – abarnert

回答

1

這裏我得到了很多不同變化的時序:

cc_explicit 5000 0.00290
cc_explicit_xrange 5000 0.00145506858826 
cc_filter 5000 0.00117516517639 
cc_genexp 5000 0.00100994110107 
cc_ifilter 5000 0.00170707702637 
cc_izip 1 3.21103000641 
cc_listcomp 5000 0.000788927078247 
cc_zip 5000 12.1080589294 

的代碼和測試驅動器是在http://pastebin.com/WSAUqTyv

由於拉鍊和izip是那麼慢,我把他們的方程並與其餘部分進行500000x10測試:

cc_explicit 500000 0.105982065201 
cc_explicit_xrange 500000 0.103507995605 
cc_filter 500000 0.0856108665466 
cc_genexp 500000 0.0679898262024 
cc_ifilter 500000 0.144966125488 
cc_listcomp 500000 0.0396680831909 

因此,最快的解決方案是listcomp。但是當我向它扔出隨機數據和更大的行時,genexpexplicit_xrange都有時擊敗listcomp,並且它們在大多數測試中都非常接近,並且genexp使用的內存要少得多,所以我願意這樣做:

def cc_genexp(grid, j, element): 
    return sum(x[j] == element for x in grid) 
0

如果我可以在這裏提供我的兩毛錢,你也應該看看Numpy,正如已經建議。或者,如果你不想處理非標準圖書館,你應該檢查出collections.Counter()。是的,它具有很大的前期成本,但如果您發現自己在同一數據集中計算了很多不同的值,您可能會發現初始投資會帶來回報。

相關問題