在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?

查看:104
本文介绍了在NumPy Python中将行广播到列时,按引用递增数组的最有效方法是什么?可以向量化吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Python中有这段代码

I have this piece of code in 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.

I wanted to vectorize or otherwise make it more efficient, i.e. faster, and if possible more economical in memory consumption. Here, my ax and ay refer to the absolute elements of an array A, while rx and ay are relative coordinates. So, I'm updating the counter array A.

我的表A可以是1000x1000,而ax,ay是100x1,cx,cy是300x1.整个过程都在循环之内,最好是优化的代码不会一直创建A大小的大表.

My table A can be 1000x1000, while ax,ay are 100x1 and cx,cy are 300x1. The whole thing's inside the loop, preferably the optimized code doesn't keep creating big tables of A size.

此问题与我之前问过,但是由于增量的工作方式,它并不直接适用于这种情况.这是一个例子.

This question is related to the one I asked before, but it's not directly applicable to this situation due to the way increment works. Here's an example.

此代码正是我想要的:

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.]])

但是,下面的代码不起作用,因为当我们增加一个数组时,它会使用该数组预先计算右侧:

However, the following code doesn't work, because when we're incrementing an array, it pre-calculates the right side with the array:

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()函数:

This solution works in terms of the correctness of numbers, but it's not the fastest, probably, because of np.add.at() function is not buffered:

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进行合并求和-

Here's one leveraging broadcasting, getting linear indices, which are then fed to the very efficient np.bincount for binned summations -

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中,请在最后一步将=替换为+=.

If you are adding into A iteratively, replace = with += there at the last step.

这篇关于在NumPy Python中将行广播到列时,按引用递增数组的最有效方法是什么?可以向量化吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆