2

Say that I have an 2d array ar like this:

0.9, 0.1, 0.3
0.4, 0.5, 0.1
0.5, 0.8, 0.5

And I want to sample from [1, 0] according to this probability array.

rdchoice = lambda x: numpy.random.choice([1, 0], p=[x, 1-x])

I have tried two methods:

1) reshape it into a 1d array first and use numpy.random.choice and then reshape it back to 2d:

np.array(list(map(rdchoice, ar.reshape((-1,))))).reshape(ar.shape)

2) use the vectorize function.

func = numpy.vectorize(rdchoice)
func(ar)

But these two ways are all too slow, and I learned that the nature of the vectorize is a for-loop and in my experiments, I found that map is no faster than vectorize.

I thought this can be done faster. If the 2d array is large it would be unbearably slow.

1
  • How fast is np.reshape([np.random.choice([0, 1], p=[x, 1-x]) for x in arr.flat], arr.shape)? Commented Feb 25, 2019 at 23:51

2 Answers 2

4

You should be able to do this like so:

>>> p = np.array([[0.9, 0.1, 0.3], [0.4, 0.5, 0.1], [0.5, 0.8, 0.5]])
>>> (np.random.rand(*p.shape) < p).astype(int)
Sign up to request clarification or add additional context in comments.

2 Comments

Great answer! Thanks very much. A follow-up. I wonder if any futher optimation would be possible if the samples are not [0, 1], say it is [-1, 1]. I know I can just add an additional step by first scaling it and then add a value: Y=2*X-1. But is it possible to do it in one step? What if the samples are arbitrary like [23, 15]?
@lerner np.where(np.random.random(p.shape) < p, 23, 15)
-1

Actually I can use the np.random.binomial:

import numpy as np
p = [[0.9, 0.1, 0.3],
     [0.4, 0.5, 0.1],
     [0.5, 0.8, 0.5]]

np.random.binomial(1, p)

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.