0

I have a 2d array of probabilities, p that sum to 1.0:

p = np.array([[0.05, 0.05, 0.1 , 0.  ],
              [0.4 , 0.1 , 0.1 , 0.2 ]])

I want to have a function that samples an index from the 2d array p based on the probabilities. For example, I should return [1,0] with a probability of 0.4 or [0,2] with a probability of 0.1.

If I call the function sample(p) which takes the 2d probability array p. Then with the 2d p array as I've defined above I could expect indices anywhere from [0,0] to [1,3] but not including [0,3] as that has a probability of 0 of appearing:

sample(p)
>> [1,0]
sample(p)
>> [0,2]
sample(p)
>> [1,0]
sample(p)
>> [1,3]

Normally I would use numpy.random.choice however it only accepts 1D array probabilities. Is there a way that I can extend this to work for 2d probability arrays of any size .

2
  • Would you please elaborate on the example? I am not really following what is happening there. Commented Apr 5, 2020 at 19:04
  • 1
    @norok2 I've added a bit more detail. Commented Apr 5, 2020 at 19:11

2 Answers 2

2

You could use np.unravel_index(), together with np.random.choice() on the result of np.arange() with the .ravel() (or .flatten()) probability.

For example:

p = np.array([[0.05, 0.05, 0.1 , 0.  ],
              [0.4 , 0.1 , 0.1 , 0.2 ]])


def sample_index(p):
    i = np.random.choice(np.arange(p.size), p=p.ravel())
    return np.unravel_index(i, p.shape)

np.random.seed(0)
x = [sample_index(p) for _ in range(10)]
print(x)
# [(1, 0), (1, 2), (1, 1), (1, 0), (1, 0), (1, 1), (1, 0), (1, 3), (1, 3), (1, 0)]
Sign up to request clarification or add additional context in comments.

Comments

1

Just make your array flat first :)

p = np.array([[0.05, 0.05, 0.1 , 0.  ],
          [0.4 , 0.1 , 0.1 , 0.2 ]])
r = np.random.choice(np.arange(8), p=p.ravel())

Ravel returns a view of your array in a one dimensional form.

p.ravel().shape
> (8,)

Just checking if its working properly:

r = np.random.choice(np.arange(8), size=10000, p=p.ravel())
np.unique(r, return_counts=True)
> (array([0, 1, 2, 4, 5, 6, 7]), array([ 530,  523,  968, 4014, 1012,  944, 2009]))

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.