user308827
user308827

Reputation: 21961

Accessing cells surrounding focal cell in numpy array

I want to extract the cells in orange and green separately in the following numpy array:

enter image description here

I could do it by hard coding e.g. arr[0, 1] refers to the top left grid cell. Is there a way to do it more elegantly?

Upvotes: 1

Views: 308

Answers (2)

ZisIsNotZis
ZisIsNotZis

Reputation: 1740

Suppose you have a N*N array called a, you can simply do:

np.concatenate((a[k:-k:N-2*k-1,k:-k], a[k+1:-k-1,k:-k:N-2*k-1]), None)

to extract the kth round (starting from zero), where the first slice stands for two rows, the second slice stands for two columns.

Example (output sorted for easier verification):

N = 8
k = 1
a = np.arange(N * N).reshape(N, N)
print(a)
print(np.sort(np.concatenate((a[k:-k:N-2*k-1,k:-k], a[k+1:-k-1,k:-k:N-2*k-1]), None)))

which will output:

[[ 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 25 26 27 28 29 30 31]
 [32 33 34 35 36 37 38 39]
 [40 41 42 43 44 45 46 47]
 [48 49 50 51 52 53 54 55]
 [56 57 58 59 60 61 62 63]]
[ 9 10 11 12 13 14 17 22 25 30 33 38 41 46 49 50 51 52 53 54]

Upvotes: 3

Rocky Li
Rocky Li

Reputation: 5958

Use a boolean mask array:

arr = np.random.permutation(np.arange(25)).reshape(5,5)

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

Above is building a random matrix for this purpose.

# Build mask
mask = np.ones((5,5)) == True
mask[1:4, 1:4] = False

>>> mask
array([[ True,  True,  True,  True,  True],
   [ True, False, False, False,  True],
   [ True, False, False, False,  True],
   [ True, False, False, False,  True],
   [ True,  True,  True,  True,  True]])

# Extract values:
>>> arr[mask]
array([15,  9,  7,  1, 22, 16, 13, 12,  6,  0, 14, 18,  5, 24, 11, 17])

Build next mask for inner circle:

mask = np.ones((5,5)) == False
mask[1:4, 1:4] = True
mask[2,2] = False

>>> mask
array([[False, False, False, False, False],
   [False,  True,  True,  True, False],
   [False,  True, False,  True, False],
   [False,  True,  True,  True, False],
   [False, False, False, False, False]])

arr[mask]
>>> array([ 0, 15, 20, 16,  4,  1,  6,  8])

Upvotes: 1

Related Questions