简化故事
假设我有一个数组arr
和索引idx
。对于idx
中出现的每个i
,我想将arr[i]
增加1。
非矢量化方法如下所示:
import numpy as np
arr = np.zeros(5)
idx = [0, 1, 1, 2, 0]
for i in idx:
arr[i] += 1
有没有办法把它矢量化?
请注意,arr[idx] += 1
是无效的,因为索引重复。
arr = np.zeros(1)
idx = [0, 0]
arr[idx] += 1 # arr becomes array([1]), not array([2])
当然,在这个1D数组例子中使用np.unique()
也可以达到同样的目的。但实际上我正在尝试处理2D数组,我怀疑计数元素是否是最好的解决方案。
编辑
np.unique
确实工作,但似乎有不必要的减速。我想要一个更快的方法(如果存在的话)。
下面是10,000个点的2D索引的示例,没有重复。
arr = np.zeros((10000, 10000))
idx = np.stack([np.arange(10000), np.arange(10000)])
%timeit np.unique(idx, axis=1, return_counts=True) # takes 1.93 ms
%timeit arr[idx[0], idx[1]] += 1 # takes 235 μs
显然,通过索引进行迭代要快10倍左右。
编辑2
@PaulS的回答比np.unique
还快。
%timeit np.add.at(arr, (idx[0], idx[1]), 1) # takes 925 μs
编辑3
下面是使用随机索引测试重复索引的示例。
arr = np.zeros((10000, 10000))
ran = (np.random.rand(10000)*10).astype(int)
idx = np.stack([ran, ran])
%timeit np.unique(idx, axis=1, return_counts=True) # takes 3.24 ms
%timeit np.add.at(arr, (idx[0], idx[1]), 1) # takes 859 μs
(edit:错别字)
详细故事
我正在尝试使用NumPy实现Hough线变换算法。(我不使用cv2.HoughLines()
的原因是因为我希望直接从点的坐标中得到结果,而不是从二进制数组中得到)。
在(r, θ)
平面上获取曲线很容易,但我在矢量化的方式下实现累加器时遇到了麻烦。目前我依赖于将2D数据平坦化为1D。是否有更好更快的方法来执行累加?
感谢您的评分
2条答案
按热度按时间2w2cym1i1#
一维数组
另一种可能的解决方案:
输出:
二维数组
(谢谢,@mozway,你的例子,我现在在这里使用。
输出:
pcww981p2#
使用
numpy.unique
获取唯一索引及其计数:更新
arr
:使用nd-arrays(2D示例):
输出:
如果索引被转置: