Fastest way to wrap a Numpy array
I am running some simulations that involve comparing values in 2D Numpy arrays multiple times with their neighbors; eg. the value at the pointer location is (y,x)
compared with the value at the pointer location (y-1,x)
from the same array.
I am currently using functions like this:
# 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
It has the ability to use either edge values or zeros for comparison on the edge of the array. Functions can also do this in any direction along any axis.
Does anyone have any suggestions for a faster way to do this? I've tried np.roll
(much slower) and this:
yf = np.ix_(range(shapey)[1:] + [shapey,], range(shapex))
shifted_array = my_array[yf]
which is slightly slower.
These functions are called ~ 200 times per second in a program that takes 10 hours, so any small speedups are more welcome!
Thank.
EDIT:
So, if the same differentiation method is required every time the shift function is called, then the Divakars method seems to offer a slight speedup, however if only the shifted array is required, then both the method and the one I am using above seem to be equal speed.
source to share
You can have offset and differentiation done in a function call, for example:
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
So the equivalent modified version syf
for runtime comparison purposes would be -
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
Runtime tests
Let's compare the equivalent version syf
with the suggested approach to runtime performance for the inputs listed in the question code -
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
So there are some improvements there!
source to share