# How to obtain a probability distribution set that sums up to 1.0 from a PDF?

I am starting from a set of percentiles and the values at the percentile from which I fitted a skew-normal distribution. So I get a CDF and a PDF function describing the distribution.

Now I'd like to generate a random sample from this distribution in python, and I was trying to use the numpy.random.choice function, to which one can pass an array of probabilities that sum up to 1.0

the code goes like:

def sample(n):
# the range of values to return
vals = np.arange(min, max, 1)
# the probability 'density' for each of the values
p = pdf(vals)
# next call fails because p.sum() does not always add up to 1.0
return np.random.choice(vals, n, p=p)


I'm just trying to figure how to generate this array from what I have.

I have a min/max for the original value range, and if I generate a range [min, max] with a spacing of 1, the sum adds up to something close to 1.0 but not quite. If i were to use a spacing of 2 or 0.5, the sum becomes close to 0.5 or close to 2.0, which makes sense since I'm sampling fewer or more values, so the sum of them follows suit.

What I'm trying to figure out is how I can generate this array of distributions that perfectly adds up to 1.0, knowing the CDF and PDF functions. It seems like I need a PMF but as I understand this is for discrete distributions; In a sense, I'm trying to discretize my continuous distribution, so it makes sense; I'm just not sure how to effectively do that.

EDIT / Solution:

Per the selected answer, the working function becomes:

def sample(n):
# the range of values to return
vals = np.arange(min, max, 1)
# the probability 'density' for each of the values
p = pdf(vals)
p = p / p.sum()
return np.random.choice(vals, n, p=p)

• I am confused: if you fit a skew-normal distribution why don't you generate from that skew-normal distribution? Using the values of a continuous cdf on a (finite) grid is not producing simulations from this distribution and the approximation can be very poor (e.g. when the grid misses modes of the continuous distribution). Commented Nov 23, 2022 at 7:04
• @Xi'an that's what I'm doing when I use pdf(vals), no? Am I missing something obvious here?
– MrE
Commented Nov 23, 2022 at 13:16
• I do not understand your code but pdf(vals) sounds like $(p(x_1),\ldots,p(x_n))$ when the $x_i$'s are the values on the grid. Commented Nov 23, 2022 at 14:36
• If you have the inverse CDF (scipy calls it ppf), just use dist.ppf(np.random.random_sample()) to sample from it directly, and the result will be much better than this. Commented Nov 23, 2022 at 17:21

Divide each number by the sum of the numbers.

$$\sum_{i=1}^N \left(\dfrac{ x_i }{ \sum_{i=1}^N x_i }\right) = \left(\dfrac{1}{ \sum_{i=1}^N x_i }\right) \sum_{i=1}^Nx_i = 1$$

This is true so long as the numbers don’t sum to zero, which your setup seems to assure will not happen.

• duh, how did I not think of that! Thanks!
– MrE
Commented Nov 22, 2022 at 23:02