6

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.

Julian Solarte
  • 555
  • 6
  • 29
  • Are there any distribution for integer numbers? – Julian Solarte Dec 03 '19 at 01:49
  • I retracted my comment 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 common discrete distributions, but won't have the summation property you desire. – RishiG Dec 03 '19 at 02:10
  • 1
    Oh -- [check this out](http://sunny.today/generate-random-integers-with-fixed-sum/). 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 Dec 03 '19 at 02:17
  • Thanks a lot it solved my problem. I have edited the question that way you can answer my question. – Julian Solarte Dec 03 '19 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 Dec 03 '19 at 16:54

3 Answers3

7

The 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).

RishiG
  • 2,790
  • 1
  • 14
  • 27
1

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)
Diogenis Siganos
  • 779
  • 7
  • 17
1

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

Sam Mason
  • 15,216
  • 1
  • 41
  • 60