2

I have a 4x4 array and wonder if there's a way to randomly sample a 2x2 square from it at any location, allowing for the square to wrapped around when it reaches an edge.

For example:

>> A = np.arange(16).reshape(4,-1)
>> start_point = A[0,3]

start_point = 3

the square would be [[15, 12], [3,0]]

2 Answers 2

2

I've generalized (a little...) my answer, permitting a rectangular input array and even a rectangular random sample

def rand_sample(arr, nr, nc):
    "sample a nr x nc submatrix starting from a random element of arr, with wrap"
    r, c = arr.shape
    i, j = np.random.randint(r), np.random.randint(c)
    r = np.arange(i, i+nr) % r
    c = np.arange(j, j+nc) % c
    return arr[r][:,c]

You may want to check that arr is a 2D array

Sign up to request clarification or add additional context in comments.

Comments

1

You could use np.lib.pad with 'wrap' option to have a padded version of the input array that has wrapped around elements at the end along the rows and columns. Finally, index into the padded array to get the desired output. Here's the implementation -

import numpy as np

# Input array and start row-col indices and neighbourhood extent
A = np.arange(42).reshape(6,-1)
start_pt = [0,3]  # start_point
N = 5   # neighbourhood extent

# Pad boundary with wrapped elements
A_pad = np.lib.pad(A, ((0,N-1),(0,N-1)), 'wrap')

# Final output after indexing into padded array
out = A_pad[start_pt[0]:start_pt[0]+N,start_pt[1]:start_pt[1]+N]

Sample run -

In [192]: A
Out[192]: 
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, 25, 26, 27],
       [28, 29, 30, 31, 32, 33, 34],
       [35, 36, 37, 38, 39, 40, 41]])

In [193]: start_pt
Out[193]: [0, 3]

In [194]: A_pad
Out[194]: 
array([[ 0,  1,  2,  3,  4,  5,  6,  0,  1,  2,  3],
       [ 7,  8,  9, 10, 11, 12, 13,  7,  8,  9, 10],
       [14, 15, 16, 17, 18, 19, 20, 14, 15, 16, 17],
       [21, 22, 23, 24, 25, 26, 27, 21, 22, 23, 24],
       [28, 29, 30, 31, 32, 33, 34, 28, 29, 30, 31],
       [35, 36, 37, 38, 39, 40, 41, 35, 36, 37, 38],
       [ 0,  1,  2,  3,  4,  5,  6,  0,  1,  2,  3],
       [ 7,  8,  9, 10, 11, 12, 13,  7,  8,  9, 10],
       [14, 15, 16, 17, 18, 19, 20, 14, 15, 16, 17],
       [21, 22, 23, 24, 25, 26, 27, 21, 22, 23, 24]])

In [195]: out
Out[195]: 
array([[ 3,  4,  5,  6,  0],
       [10, 11, 12, 13,  7],
       [17, 18, 19, 20, 14],
       [24, 25, 26, 27, 21],
       [31, 32, 33, 34, 28]])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.