繁体   English   中英

在 NumPy Python 中广播行到列时通过引用增加数组的最有效方法是什么? 可以矢量化吗?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM