Given a 2d matrix, for instance:
A = array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
how can I select NxN
window around a given element so that the window is filled with an arbitrary (e.g. mean) value if it goes outside the original array?
Example:
neighbors(A, x=0, y=0, N=3)
would yield
array([[ 2.5, 2.5, 2.5],
[ 2.5, 0, 1],
[ 2.5, 4, 5]])
You can slice a numpy array is a similar way to slicing a list - except you can do it in more than one dimension. As with indexing, the array you get back when you index or slice a numpy array is a view of the original array. It is the same data, just accessed in a different order.
Slice Two-dimensional Numpy Arrays To slice elements from two-dimensional arrays, you need to specify both a row index and a column index as [row_index, column_index] . For example, you can use the index [1,2] to query the element at the second row, third column in precip_2002_2013 .
One-Dimensional Slicing The first item of the array can be sliced by specifying a slice that starts at index 0 and ends at index 1 (one item before the 'to' index). Running the example returns a subarray with the first element. We can also use negative indexes in slices.
You can pad your array. Padding will extend your array with the desired boundary conditions (see the mode
parameter for all possible options):
>>> A = np.array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]])
>>> N = 5 # 5x5 windows
>>> B = np.pad(A, N//2, mode='reflect')
>>> B
array([[10, 9, 8, 9, 10, 11, 10, 9],
[ 6, 5, 4, 5, 6, 7, 6, 5],
[ 2, 1, 0, 1, 2, 3, 2, 1],
[ 6, 5, 4, 5, 6, 7, 6, 5],
[10, 9, 8, 9, 10, 11, 10, 9],
[14, 13, 12, 13, 14, 15, 14, 13],
[10, 9, 8, 9, 10, 11, 10, 9],
[ 6, 5, 4, 5, 6, 7, 6, 5]])
As you can see, the original array is in the center of the matrix, padded by 2 rows and 2 columns (N//2 = 5//2 = 2
, both from lef/right and bottom/top). The padded elements are reflected.
For this new array, you can access to the desired neighbours window by just normally indexing the array:
>>> x = 1; y = 1 # corresponds to number 5 in the original array
>>> B[y:y+N, x:x+N]
array([[ 5, 4, 5, 6, 7],
[ 1, 0, 1, 2, 3],
[ 5, 4, 5, 6, 7],
[ 9, 8, 9, 10, 11],
[13, 12, 13, 14, 15]])
You can choose other padding methods, mean is one of the options.
I think this is not too far off:
def neighbors(arr, x, y, N):
left = max(0, x - N)
right = min(arr.shape[0], x + N)
top = max(0, y - N)
bottom = min(arr.shape[1], y + N)
window = arr[left:right+1,top:bottom+1]
fillval = window.mean()
result = np.empty((2*N+1, 2*N+1))
result[:] = fillval
ll = N - x
tt = N - y
result[ll+left:ll+right+1,tt+top:tt+bottom+1] = window
return result
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With