所以我有这个数组,对吧?
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.])
。
我希望这能用于多维数组和可广播索引以及所有这些。有什么想法吗?
答案 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