将Numpy数组快速移位的最佳方法

8
我将运行一些涉及重复比较2D Numpy数组中值的模拟,例如,与其“邻居”相比较;例如,在同一数组中,指数位置(y,x)处的值与位置(y-1,x)处的指数位置的值进行比较。

目前我正在使用以下函数:

# example of the typical size of the arrays
my_array = np.ndarray((500,500))    

shapey, shapex = my_array.shape
Yshape = (1, shapex)
Yzeros = np.zeros((1, shapex))

def syf(A, E=True):
    if E == True:
        return np.concatenate((A[1:], A[-1].reshape(Yshape)), axis=0)
    else:
        return np.concatenate((A[1:], Yzeros), axis=0)

shifted_array = syf(my_array)

difference_in_y = shifted_array - my_array 

这个选项可以在数组边缘使用边缘值或零进行比较。这些函数还可以在任何轴上的任何方向上执行。有没有人对更快的方法有建议?我已经尝试过np.roll(速度慢得多)和这个:
yf = np.ix_(range(shapey)[1:] + [shapey,], range(shapex))
shifted_array = my_array[yf]

这个方法稍微慢一些。

这些函数在一个运行时间为10小时的程序中被调用约200次,因此任何小的加速都是受欢迎的!

谢谢。

编辑:

如果每次调用shift函数时都需要相同的差分方法,则Divakars方法似乎可以提供轻微的加速,但是如果只需要一个移位数组,那么上面使用的方法和那个方法的速度是相等的。


我原本打算建议使用scipy.ndimage.convolve1d,但对于这种情况(非常短的滤波器),它实际上比您当前的方法慢了约2倍。 - Joe Kington
看一下 roll 的代码,它生成了一个类似于你的 yf 的索引,然后使用了 take - hpaulj
考虑到新数组与旧数组几乎相同,我很惊讶为什么没有更快的通过索引来完成此操作的方法,以避免在内存中创建新数组。尽管我猜测如果“roll”使用“np.ix_”索引,则可能没有更快的替代方法。 - Siyh
1个回答

5
您可以在函数调用中完成移位和差分操作,例如:
def syf1(A, E=True):
    out = np.empty_like(A)
    out[:-1] = A[1:] - A[:-1] # Or np.diff(my_array,axis=0)
    if E == True:
        out[-1] = 0
    else:
        out[-1] = -A[-1]
    return out

因此,为了进行运行时比较,syf的等效修改版本应该是 -
def syf(A, E=True):
    if E == True:
        return np.concatenate((A[1:], A[-1].reshape(Yshape)), axis=0) - A
    else:
        return np.concatenate((A[1:], Yzeros), axis=0) - A

运行时测试

让我们比较在问题代码中列出的输入上,syf 的等效版本和所提出的方法的运行时性能 -

In [113]: %timeit syf(my_array)
1000 loops, best of 3: 518 µs per loop

In [114]: %timeit syf1(my_array)
1000 loops, best of 3: 494 µs per loop

所以,有一些改进!

不要忘记你可以只写 if E: !! - Matthew
@Matthew 谢谢你的提示。我现在会保持不变,因为这只是个小事,等到 OP 给出反馈再说吧。无论如何,非常感谢你的建议! - Divakar
@Matthew 谢谢你的提示,我有一种感觉,因为我是通过(非常)非正式的方式学习编程,所以有很多像这样的小事情我不知道。 - Siyh
@Siyh 如果你找到了更快/更好的解决方案,与SO社区分享它作为你自己的解决方案会很不错。 - Divakar
@Siyh 我也是一样,这就是我开始浏览SO的原因。无论如何,你应该添加一个答案或者发布自己的问题,以便如果其他人遇到类似的问题时可以参考! :) - Matthew
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接