Reputation: 6509
Assume I have a list of values, for example:
limits = [10, 6, 3, 5, 1]
For every item in limits
, I need to generate a random number less than or equal to the item. However, the catch is that the sum of elements in the new random list must be equal to a specified total.
For example if total = 10
, then one possible random list is:
random_list = [2, 1, 3, 4, 0]
where you see random_list
has same length as limits
, every element in random_list
is less than or equal to the corresponding element in limits
, and sum(random_list) = total
.
How to generate such a list? I am open (and prefer) to use numpy, scipy, or pandas.
Upvotes: 0
Views: 345
Reputation: 6509
Found what I was looking for: The hypergeometric distribution which is similar to the binomial, but without replacement.
The distribution available in numpy:
import numpy as np
gen = np.random.Generator(np.random.PCG64(seed))
random_list = gen.multivariate_hypergeometric(limits, total)
# array([4, 4, 1, 1, 0])
Also to make sure I didn't misunderstand the distribution did a sanity check with 10 million samples and check that the maximum is always within the limits
res = gen.multivariate_hypergeometric(limits, total, size=10000000)
res.max(axis=0)
# array([10, 6, 3, 5, 1])
which is same as limits
.
Upvotes: 1