2015-05-14 64 views
1

所以我有這個數組,對吧?分配給數組,添加索引的多個副本

a=np.zeros(5) 

我想在給定的索引處添加值,其中索引可以是重複的。

例如

a[[1, 2, 2]] += [1, 2, 3] 

我想這產生array([ 0., 1., 5., 0., 0.]),但我得到的答覆是array([ 0., 1., 3., 0., 0.])

我想這與多維數組和可廣播索引一起工作。有任何想法嗎?

回答

3

您需要使用np.add.at來解決與+=遇到的緩衝問題(值不會累積在重複的索引處)。指定數組,索引,值這些索引在地方加入:

>>> a = np.zeros(5) 
>>> np.add.at(a, [1, 2, 2], [1, 2, 3]) 
>>> a 
array([ 0., 1., 5., 0., 0.]) 

at是其他ufuncs的一部分太(乘法,除法等)。此方法也適用於多維數組。

1

您正在執行的操作可以看作分箱,並且在技術上更具體,您正在做加權分塊,這些值是權重,索引是分箱。對於這種分檔操作,您可以使用np.bincount

這裏的執行 -

import numpy as np 

a=np.zeros(5)  # initialize output array 

idx = [1, 2, 2]  # indices 
vals = [1, 2, 3]  # values 

a[:max(idx)+1] = np.bincount(idx,vals) # finally store the bincounts 

運行測試

這裏有兩組輸入的一些運行時測試datasizes比較建議bincount基礎的方法,並在other answer列出的add.at基礎的方法:

Datasize#1 -

In [251]: a=np.zeros(1000) 
    ...: idx = np.sort(np.random.randint(1,1000,(500))).tolist() 
    ...: vals = np.random.rand(500).tolist() 
    ...: 

In [252]: %timeit np.add.at(a, idx, vals) 
10000 loops, best of 3: 63.4 µs per loop 

In [253]: %timeit a[:max(idx)+1] = np.bincount(idx,vals) 
10000 loops, best of 3: 42.4 µs per loop 

數據尺寸#2 -

In [254]: a=np.zeros(10000) 
    ...: idx = np.sort(np.random.randint(1,10000,(5000))).tolist() 
    ...: vals = np.random.rand(5000).tolist() 
    ...: 

In [255]: %timeit np.add.at(a, idx, vals) 
1000 loops, best of 3: 597 µs per loop 

In [256]: %timeit a[:max(idx)+1] = np.bincount(idx,vals) 
1000 loops, best of 3: 404 µs per loop