2013-03-27 118 views
1

我有一個非常非常非常大的二維數組 - 大約有一千列的數量級,但有幾百萬行(足以使它不適合內存在我的32GB機器上)。我想計算千列中每一列的方差。一個關鍵的事實有助於:我的數據是8位無符號整數。使用numpy數組有效索引numpy數組

下面是我正在計劃如何解決這個問題。我將首先構造一個新的二維數組,稱爲計數與形狀(1000,256),與想法counts[i,:] == np.bincount(bigarray[:,i])。一旦有了這個數組,計算方差就會變得微不足道。

問題是,我不確定如何有效地進行計算(此計算必須實時運行,並且我希望帶寬受限於SSD可以返回數據的速度)。這裏的東西它的工作原理,但神可怕的慢:

counts = np.array((1000,256)) 
for row in iterator_over_bigaray_rows(): 
    for i,val in enumerate(row): 
     counts[i,val] += 1 

有什麼辦法來寫這個跑得更快?事情是這樣的:

counts = np.array((1000,256)) 
for row in iterator_over_bigaray_rows(): 
    counts[i,:] = // magic np one-liner to do what I want 
+0

+1對付一個巨大的數組的聰明的方式!但是你仍然需要迭代很多行... – Jaime 2013-03-27 20:55:23

+0

是的,但是不能避免這種情況。我實際上並沒有像這樣迭代它(我以塊的形式從磁盤加載它,然後異步地遍歷塊)。 – 2013-03-27 21:09:33

回答

1

我想這是你想要的東西:

counts[np.arange(1000), row] += 1 

但是如果你的陣列具有數百萬行的,你還是不得不遍歷數以百萬計的那些。現在

chunk = np.random.randint(256, size=(1000, 1000)) 

def count_chunk(chunk): 
    rows, cols = chunk.shape 
    col_idx = np.arange(cols) * 256 
    counts = np.bincount((col_idx[None, :] + chunk).ravel(), 
         minlength=256*cols) 
    return counts.reshape(-1, 256) 

def count_chunk_by_rows(chunk): 
    counts = np.zeros(chunk.shape[1:]+(256,), dtype=np.int) 
    indices = np.arange(chunk.shape[-1]) 
    for row in chunk: 
     counts[indices, row] += 1 
    return counts 

而且:下面的技巧給了接近5倍加速我的系統上

In [2]: c = count_chunk_by_rows(chunk) 

In [3]: d = count_chunk(chunk) 

In [4]: np.all(c == d) 
Out[4]: True 

In [5]: %timeit count_chunk_by_rows(chunk) 
10 loops, best of 3: 80.5 ms per loop 

In [6]: %timeit count_chunk(chunk) 
100 loops, best of 3: 13.8 ms per loop 
+0

就是這樣。 – 2013-03-27 21:24:23

+1

@michaeldillard請參閱編輯一些額外的速度。 – Jaime 2013-03-27 22:09:12