Python 如何通过移位数组对numpy数组中的值进行局部移位?

Python 如何通过移位数组对numpy数组中的值进行局部移位?,python,arrays,numpy,Python,Arrays,Numpy,比如说,我有一个初始2D数组,其中包含一些数字: initial=np.array([[1,2,3,4], [5, 6, 7, 8]]) 还有另外两个形状相同的数组:第一个数组包含按行的单位移位,第二个数组包含按列的单位移位(假设它们的构造是为了避免越界): rowShifts=np.array([[0,0,1,0], [0, 0, -1, 0]]) colShifts=np.array([[0,1,0,-1], [0, 0, 1, 0]]) 我怎样才能得到一个数组,它与初始数组一致,除了

比如说,我有一个初始2D数组,其中包含一些数字:

initial=np.array([[1,2,3,4],
[5, 6, 7, 8]])
还有另外两个形状相同的数组:第一个数组包含按行的单位移位,第二个数组包含按列的单位移位(假设它们的构造是为了避免越界):

rowShifts=np.array([[0,0,1,0],
[0, 0, -1, 0]])
colShifts=np.array([[0,1,0,-1],
[0, 0, 1,  0]])
我怎样才能得到一个数组,它与初始数组一致,除了元素之外,应该根据这两个数组进行移位

result=np.array([[1,3,7,3],
[5, 6, 4, 8]])
显然,可以使用循环来完成,但在实际情况下,性能是不可接受的

另一种可能的解决方案是使用恒定的偏移量复制初始阵列,并按条件选择值,但对于大型3D阵列,这种方法将消耗大量内存


有没有合适的解决方案,在内存和性能方面不会太重?

您可以创建网格、偏移和索引



如果移位很少,即如果行移位/列移位中有许多零,则稀疏方案可能会节省一些时间。使用1000x1000网格进行试验时,我看到在大约20%的非零位移下发生交叉:


使用
ogrid
提高效率?是的,当然更可取!
xs, ys = initial.shape
rm, cm = np.ogrid[:xs, :ys]

initial[rm + rowShifts, cm + colShifts]
array([[1, 3, 7, 3],
       [5, 6, 4, 8]])
from simple_benchmark import BenchmarkBuilder, MultiArgument
import numpy as np

B = BenchmarkBuilder()

@B.add_function()
def ogrid(data,rowo,colo):
    xs, ys = data.shape
    rm, cm = np.ogrid[:xs, :ys]
    return data[rm + rowo, cm + colo]

@B.add_function()
def sparse(data,rowo,colo):
    nz = np.where(rowo.astype(bool) | colo.astype(bool))
    result = data.copy()
    result[nz] = data[nz[0]+rowo[nz],nz[1]+colo[nz]]
    return result

@B.add_arguments('number of shiftees')
def argument_provider():
    data = np.arange(1000000).reshape(1000,1000)
    for exp in range(8, 40):
        nsh = int(1.4**exp)
        shifts = np.random.randint(0,1000,(2,2,nsh))
        rowo = np.zeros((1000,1000),int)
        colo = np.zeros((1000,1000),int)
        rowo[shifts[0,0],shifts[1,0]] = shifts[0,1]-shifts[0,0]
        colo[shifts[0,0],shifts[1,0]] = shifts[1,1]-shifts[1,0]
        yield np.count_nonzero(rowo.astype(bool) | colo.astype(bool)), \
            MultiArgument([data,rowo,colo])

r = B.run()
r.plot()

import pylab
pylab.savefig('bm.png')