user2667066
user2667066

Reputation: 2079

Generate random integers from successively decreasing ranges in numpy

I want to generate N random integers, where the first integer is uniformly chosen from 0..N, the second is uniformly chosen from 0..(N-1), the third from 0..(N-2), and so on. Is there a way to do this quickly in numpy, without incurring the cost of performing a separate numpy call N times?

Upvotes: 0

Views: 375

Answers (2)

Warren Weckesser
Warren Weckesser

Reputation: 114781

You can pass arrays as the arguments to the integers method of numpy's random generator class. The arguments will broadcast, and generate the appropriate values.

For example,

In [17]: import numpy as np                                        

In [18]: rng = np.random.default_rng()

In [19]: N = 16                                                                                                           

In [20]: rng.integers(0, np.arange(N, 0, -1))                                        
Out[20]: array([13, 10, 11, 11,  9,  8,  3,  0,  2,  5,  3,  1,  0,  2,  0,  0])

Note that the upper value given to the integers method is excluded, so if the ranges that you stated are inclusive, you'll have to adjust the arange arguments appropriately:

In [24]: rng.integers(0, np.arange(N+1, 1, -1))                                                                           
Out[24]: array([ 6,  9, 11, 11,  7,  2,  5,  5,  8,  7,  5,  5,  4,  0,  1,  0])

Upvotes: 1

Quang Hoang
Quang Hoang

Reputation: 150735

We can sample random numbers uniformly in (0,1) and scale, then convert to int:

N = 10
np.random.seed(10)
randoms = np.random.rand(N)

(randoms * np.arange(1,N+1)).astype(int)

Output:

array([0, 0, 1, 2, 2, 1, 1, 6, 1, 0])

Upvotes: 1

Related Questions