用重复索引递增Numpy数组

26 投票
3 回答
12910 浏览
提问于 2025-04-15 17:38

我有一个Numpy数组,还有一个索引列表,我想把这些索引对应的值都加一。这个列表可能会有重复的索引,我希望加一的次数能根据每个索引出现的次数来调整。如果没有重复的索引,操作起来就很简单:

a=np.zeros(6).astype('int')
b=[3,2,5]
a[b]+=1

但是如果有重复的索引,我想出了以下的方法。

b=[3,2,5,2]                     # indices to increment by one each replicate
bbins=np.bincount(b)
b.sort()                        # sort b because bincount is sorted
incr=bbins[np.nonzero(bbins)]   # create increment array
bu=np.unique(b)                 # sorted, unique indices (len(bu)=len(incr))
a[bu]+=incr

这样做是最好的方法吗?我是否有风险假设 np.bincountnp.unique 的操作结果会保持相同的排序?我是不是漏掉了什么简单的Numpy操作可以解决这个问题?

3 个回答

1

如果 ba 的一个小范围,我们可以这样进一步完善 Alok 的回答:

import numpy as np
a = np.zeros( 100000, int )
b = np.array( [99999, 99997, 99999] )

blo, bhi = b.min(), b.max()
bbins = np.bincount( b - blo )
a[blo:bhi+1] += bbins

print a[blo:bhi+1]  # 1 0 2
43

在numpy版本大于等于1.8时,你可以使用加法的“通用函数”(也叫ufunc)中的at方法。正如文档中提到的

对于加法的ufunc,这个方法相当于 a[indices] += b,不过它会对那些被多次索引的元素进行累加。

所以以你的例子为例:

a = np.zeros(6).astype('int')
b = [3, 2, 5, 2]

…然后…

np.add.at(a, b, 1)

…会让a变成…

array([0, 0, 2, 1, 0, 1])
6

在你执行完

bbins=np.bincount(b)

之后,为什么不试试:

a[:len(bbins)] += bbins

(为了进一步简化,进行了编辑。)

撰写回答