I have a numpy array, and I want to get the "neighbourhood" of the i'th point. Usually the arrays I'm using are two-dimensional, but the following 1D example illustrates what I'm looking for. If
A = numpy.array([0,10,20,30,40,50,60,70,80,90])
Then the (size 5) neighbourhood of element 4 is [20,30,40,50,60]
, and this can easily be obtained by doing A[i-2:i+3]
.
However, I also need the neighbourhoods to "wrap around" the edges of the array, so that the neighbourhood of the element 0 is [80,90,0,10,20]
and the neighbourhood of the element 9 is [70,80,90,0,10]
. I can't seem to find an elegant way to do this, so I end up having to use some complicated, annoying logic every time this comes up (which is very often for me). In the 2D case the neighbourhood of a point would be a rectangular array.
So my question is, is there a neat way to expres this "wrap-around neighbourhood" operation in numpy? I would prefer something that returns a slice rather than a copy, but readability and speed are the most important considerations.
you can use argument
axis=0
ofnumpy.take
for n-d array.The same
axis=0
will work for n*m dimensions...numpy.take
in'wrap'
mode will use your indices modulo the length of the array.See documentation for details
numpy.take
numpy.roll can shift the array such that the entire slice is at the beginning of the array. Then take your slice at the beginning and numpy.roll again to revert the array back to its original position.
numpy.roll doesn't perform well for me on large arrays however.
I know this question is old, but should mention scipy.ndimage.filter.generic_filter.
It has a
mode='wrap'
option, plus it handles the application of the neighbor function.Say you have a neighbor function:
To apply the neighbor function to every 5, with wrapped values at the edges:
Note: For cases where your neighbors do not require wrapping,
numpy.take
is slower than simply taking a sliceA[i-2:i+3]
. You may want to wrap your neighbors function with some conditional statements:If you find yourself taking neighbors while iterating through an array, like in a centered moving average, you'll find that this requires less time, especially for longer arrays:
Here is the moving average function I used:
I'm sure these function can be improved further. I'm open to suggestions.
You can use the np.pad routine like this:
Say you have a neighbor function:
To apply the neighbor function to every 5 you need to be careful about your start and end indices (in the range(...) command) and the relative slice you take from A.