I want to make a list of N random INTEGER numbers whose sum is equal to M number.
I have used numpy and dirichlet function in Python, but this generate double random number array, I would like to generate integer random number.
import numpy as np
np.random.dirichlet(np.ones(n))*m
The solution can use other distribution the sense is resolve the problem.
I want to make a list of N random INTEGER numbers whose sum is equal to M number.
I have used numpy and dirichlet function in Python, but this generate double random number array, I would like to generate integer random number.
import numpy as np
np.random.dirichlet(np.ones(n))*m
The solution can use other distribution the sense is resolve the problem.
Share Improve this question edited Dec 3, 2019 at 14:30 Julian Solarte asked Dec 3, 2019 at 1:30 Julian SolarteJulian Solarte 5858 silver badges31 bronze badges 5- Are there any distribution for integer numbers? – Julian Solarte Commented Dec 3, 2019 at 1:49
-
I retracted my ment because I saw that you were multiplying by
m
, so you do end up with something that can be truncated, but the fact does remain that Dirichlet is by definition a distribution of real numbers. Binomial and Poisson are two mon discrete distributions, but won't have the summation property you desire. – RishiG Commented Dec 3, 2019 at 2:10 - 1 Oh -- check this out. Looks like multinomial is the way to go. The distribution won't be the same as Dirichlet, but the numbers will add up, which is not guaranteed if you truncate Dirichlet. – RishiG Commented Dec 3, 2019 at 2:17
- Thanks a lot it solved my problem. I have edited the question that way you can answer my question. – Julian Solarte Commented Dec 3, 2019 at 14:31
- No worries. I don't really care about acceptance on this one, I was mostly interested in finding the answer too. Wrote up an answer just because I had the info bouncing around. – RishiG Commented Dec 3, 2019 at 16:54
3 Answers
Reset to default 7The problem with using dirichlet
for this is that it is a distribution over real numbers. It will yield a vector of numbers in the range (0,1)
, which sum to 1, but truncating or rounding them may remove the guarantee of a specific sum. Following this post we can get the desired effect from the multinomial
distribution (using np.random.multinomial
), as follows:
from numpy.random import multinomial
np.random.multinomial(m, np.ones(n)/n)
This will generate n
integers between 0
and m
, whose sum is m
, with equal probability of drawing a given position. The easiest way to visualize this is to consider the result as describing a set of draws from a fixed set of objects (e.g., die rolls drawing from the integers from 1 to 6) where the final array is the number of times the corresponding object was drawn. The total will always sum to the given number of total draws (rolls).
note that a Dirichlet distribution can be used to parametrize a multinomial, giving control over the smoothness or "uniformity" of the bins, e.g:
import numpy as np
m = 50
n = 5
s = 0.1
np.random.multinomial(m, np.random.dirichlet(np.ones(n) * s))
mostly parameterised as @Bonfire, but larger values of s
(e.g. try s=100
) causing the bins to approach Poisson with mean=m/n
and smaller values leading to greater variance
Here is a sample solution:
import numpy as np
M = 50 # The fixed sum
N = 5 # The amount of numbers
array = np.random.multinomial(M, np.ones(N) / N)[0]
print(array)