![](/img/trans.png)
[英]What's the most efficient way to sum up an ndarray in numpy while minimizing floating point inaccuracy?
[英]What's the most efficient way to increment an array by a reference while broadcasting row to column in NumPy Python? Can it be vectorized?
我在 Python 中有这段代码
for i in range(len(ax)):
for j in range(len(rx)):
x = ax[i] + rx[j]
y = ay[i] + ry[j]
A[x,y] = A[x,y] + 1
在哪里
A.shape = (N,M)
ax.shape = ay.shape = (L)
rx.shape = ry.shape = (K)
我想矢量化或以其他方式使其更高效,即更快,并且如果可能的话在内存消耗方面更经济。 这里,我的 ax 和 ay 指的是数组 A 的绝对元素,而 rx 和 ay 是相对坐标。 所以,我正在更新计数器数组 A。
我的表 A 可以是 1000x1000,而 ax,ay 是 100x1,而 cx,cy 是 300x1。 整个事情都在循环内,最好是优化的代码不会一直创建 A 大小的大表。
这个问题与我之前问过的问题有关,但由于增量的工作方式,它并不直接适用于这种情况。 这是一个例子。
这段代码完全符合我的要求:
import numpy as np
A = np.zeros((4,5))
ax = np.arange(1,3)
ay = np.array([1,1])
rx = np.array([-1,0,0])
ry = np.array([0,0,0])
for i in range(len(ax)):
for j in range(len(rx)):
x = ax[i] + rx[j]
y = ay[i] + ry[j]
print(x,y)
A[x,y] = A[x,y] + 1
A
array([[ 0., 1., 0., 0., 0.],
[ 0., 3., 0., 0., 0.],
[ 0., 2., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]])
但是,以下代码不起作用,因为当我们递增数组时,它会预先计算数组的右侧:
import numpy as np
A = np.zeros((4,5))
ax = np.arange(1,3)
ay = np.array([1,1])
rx = np.array([-1,0])
ry = np.array([0,0])
x = ax + rx[:,np.newaxis]
y = ay + ry[:,np.newaxis]
A[x,y] = A[x,y] + 1
A
array([[ 0., 1., 0., 0., 0.],
[ 0., 1., 0., 0., 0.],
[ 0., 1., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]])
这个解决方案在数字的正确性方面有效,但它不是最快的,可能是因为 np.add.at() 函数没有被缓冲:
import numpy as np
A = np.zeros((4,5))
ax = np.arange(1,3)
ay = np.array([1,1])
rx = np.array([-1,0,0])
ry = np.array([0,0,0])
x = ax + rx[:,np.newaxis]
y = ay + ry[:,np.newaxis]
np.add.at(A,[x,y],1)
A
这是一种利用broadcasting
,获取线性索引,然后将其馈送到非常有效的np.bincount
进行分箱求和的方法 -
m,n = 4,5 # shape of output array
X = ax[:,None] + rx
Y = ay[:,None] + ry
Aout = np.bincount((X*n + Y).ravel(), minlength=m*n).reshape(m,n)
使用np.flatnonzero
替代方案 -
idx = (X*n + Y).ravel()
idx.sort()
m = np.r_[True,idx[1:] != idx[:-1],True]
A.ravel()[idx[m[:-1]]] = np.diff(np.flatnonzero(m))
如果您要迭代地添加到A
,请在最后一步将=
替换=
+=
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.