Given a positive integer array a
, the goal is to generate 5 random numbers based on the weight they have in the array.
For example:
a = [2,3,4,4,4,4,4,6,7,8,9]
In this case the number 4 has appeared 5 times, in this case the number 4 should have the probability of 5/11 to appear.
No numbers should be repeated.
Given a
, an array of positive integers, you'll first need to compute the frequency of each integer. For example, using bincount
:
>>> a = [2,3,4,4,4,4,4,4,5,6,7,8,9,4,9,2,3,6,3,1]
>>> b = np.bincount(a)
b
tells you the frequency of each integer in a
. The corresponding set of weights is therefore the array b/len(a)
. Using np.random.choice
with these weights and replace=False
should then give you what you need:
>>> np.random.choice(np.arange(len(b)), 5, p=b/len(a), replace=False)
array([5, 9, 4, 3, 8])
>>> np.random.choice(np.arange(len(b)), 5, p=b/len(a), replace=False)
array([7, 4, 6, 9, 1])
>>> np.random.choice(np.arange(len(b)), 5, p=b/len(a), replace=False)
array([3, 7, 4, 9, 6])
If you're not working with only positive integers, or if you are working with large positive integers, @user2357112 points out in the comments below that np.unique
provides another solution. Here you'd write:
>>> choices, counts = np.unique(a, return_counts=True)
>>> np.random.choice(choices, 5, p=counts/len(a), replace=False)
array([9, 8, 2, 4, 5])
You probably looking for numpy.random.multinomial
For example np.random.multinomial(1, [1/6.]*6, size=1)
is throwing fair dice once.
After you get an result you can update probability vector(must sum to 1) as you desire. For example numpy.random.multinomial(1, [1/2., 1/2., 0., 0., 0., 0.], size=1)
.
The simplest solution (and perhaps most inefficient) can be as follows:
import random
def get_randoms(n, a):
a = a[:]
r = []
for i in range(n):
r.append(random.choice(a))
a = [y for y in a if y != r[-1]]
return r
print get_randoms(5, [2,3,4,4,4,4,4,4,5,6,7,8,9,4,9,2,3,6,3,1])
The output can would be something like
[8, 2, 3, 6, 9]