Home > Mobile >  Numpy subarrays and relative indexing
Numpy subarrays and relative indexing

Time:01-11

I have been searching if there is an standard mehtod to create a subarray using relative indexes. Take the following array into consideration:

>>> m = np.arange(25).reshape([5, 5])
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [20, 21, 22, 23, 24]])

I want to access the 3x3 matrix at a specific array position, for example [2,2]:

>>> x = 2, y = 2
>>> m[slice(x-1,x 2), slice(y-1,y 2)]
array([[ 6,  7,  8],
       [11, 12, 13],
       [16, 17, 18]])

For example for the above somethig like m.subarray(pos=[2,2], shape=[3,3]) I want to sample a ndarray of n dimensions on a specific position which might change.

I did not want to use a loop as it might be inneficient. Scipy functions correlate and convolve do this very efficiently, but for all positions. I am interested only in the sampling of one.

The best answer could solve the issues at edges, in my case I would like for example to have wrap mode: (a b c d | a b c d | a b c d)

--------------------EDITED-----------------------------

Based on the answer from @Carlos Horn, I could create the following function.

def cell_neighbours(array, index, shape):  
    pads = [(floor(dim/2), ceil(dim / 2)) for dim in shape]
    array = np.pad(self.configuration, pads, "wrap")
    views = np.lib.stride_tricks.sliding_window_view
    return views(array, shape)[tuple(index)]

Last concern might be about speed, from docs: For many applications using a sliding window view can be convenient, but potentially very slow. Often specialized solutions exist.

From here maybe is easier to get a faster solution.

CodePudding user response:

You could build a view of 3x3 matrices into the array as follows:

import numpy as np
m = np.arange(25).reshape(5,5)
m3x3view = np.lib.stride_tricks.sliding_window_view(m, (3,3))

Note that it will change slightly your indexing on half the window size meaning

x_view = x - 3//2
y_view = y - 3//2
print(m3x3view[x_view,y_view])  # gives your result

In case a copy operation is fine, you could use:

mpad = np.pad(m, 1, mode="wrap")
mpad3x3view = np.lib.stride_tricks.sliding_window_view(mpad, (3,3))
print(mpad3x3view[x % 5,y % 5])

to use arbitrary x, y integer values.

  • Related