分配给数组,添加索引

时间:2015-05-14 11:41:37

标签: python arrays numpy multidimensional-array

所以我有这个数组,对吧?

a=np.zeros(5)

我想在给定的索引处为其添加值,其中索引可以是重复的。

e.g。

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

我希望这会产生array([ 0., 1., 5., 0., 0.]),但我得到的答案是array([ 0., 1., 3., 0., 0.])

我希望这能用于多维数组和可广播索引以及所有这些。有什么想法吗?

2 个答案:

答案 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也是其他ufunc的一部分(乘法,除法等)。此方法也适用于多维数组。

答案 1 :(得分:1)

您正在执行的操作可以看作是分箱,从技术角度来看,您正在进行加权bining ,其中这些值是权重,索引是分档。对于此类分箱操作,您可以使用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

运行时测试

以下是两组输入数据的一些运行时测试,比较了基于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

Datasize#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