2013-03-27 119 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