dgketchum
dgketchum

Reputation: 311

Randomly place n elements in a 2D array

I need a boolean or binary numpy array size (m,m) with n True values scattered randomly. I'm trying to make a random grid pattern. I will have a 5x5 array with 3 True values over it and will sample at those points only.
Using random.choice I sometimes get more or less than the 3 desired True values.

for x in range(0,25):
    x = np.random.choice([True,False], p=[0.15,0.85])

Upvotes: 2

Views: 2579

Answers (2)

pjs
pjs

Reputation: 19855

You can do it straightforwardly with shuffle:

n = 3; m = 5
x = [True] * n + [False] * (m * m - n)
np.random.shuffle(x)
result = np.mat(x).reshape(m, m)

Upvotes: 3

Divakar
Divakar

Reputation: 221584

You could use np.random.choice with the optional argument replace set as False to have unique random IDs from 0 to m*m-1 that could be set to ones in a zeros initialized 2D array using linear indexing with np.put. Thus, the implementation would look something like this -

m = 5; n = 3;
out = np.zeros((m,m),dtype=bool)
np.put(out,np.random.choice(range(m*m), n, replace=False),1)

Sample run -

In [54]: m = 5; n = 3;
    ...: out = np.zeros((m,m),dtype=bool)
    ...: np.put(out,np.random.choice(range(m*m), n, replace=False),1)
    ...: 

In [55]: out
Out[55]: 
array([[False, False, False, False, False],
       [False, False, False, False, False],
       [False,  True,  True, False, False],
       [False, False, False, False, False],
       [False, False, False,  True, False]], dtype=bool)

Since it's a case of linear indexing, at the last step, you could also do -

out.ravel()[np.random.choice(range(m*m), n, replace=False)] = 1

Upvotes: 4

Related Questions