# Random Distribution to fit an Average Python

This is from my own question on Stack Overflow.

I want to get average numbers from a range such that they fit an intended average. I expect something bell-curve-like, but asymmetrical unless the average is the mean of the range. The function should allow for any degree of deviation. In my Overflow question, I wanted it to pick from a list, but that's an easy modification if my idea works.

This is what I've come up with: (imports: numpy and random)

def randlist(minn, maxn, goaln, countn):
nlist = []
for i in range(0, countn):
if len(nlist) > 10:
ave = numpy.mean(nlist)
if ave > goaln:
a = random.uniform(minn, goaln)
else:
a = random.uniform(goaln, maxn)
else:
a = random.uniform(minn, maxn)
nlist.append(a)
return nlist


Trying it out:

b = randlist(1, 10, 7, 1000)
print len(b)
>> 1000
print numpy.mean(b)
>> 6.99951157861


I'm no mathematician; is this as functional as it appears to me to be?

• Did you look at a random.betavariate? – vnp Nov 19 '14 at 21:30
• That's a "weird" distribution. What do you intend to use it for? – 200_success Nov 19 '14 at 21:37
• Quality scores for leads: 400,000 leads to call from call centers. I've already done the work of sorting them into assumed scores - but when I load them to be called, say 10,000 at a time, I don't want to exclude everything below 5.0 in the case of picking an average score of 7.5. Everyone should be potentially called. The bell curve formulas I've seen limit for symmetry. – Xodarap777 Nov 19 '14 at 23:03

If you want to express the field or distribution in a wave form, you should consider doing a Fourier Transformation on the function. Now, I must admit that I haven't understood exactly the sort of distribution function you are looking for. Numpy already has implementations for Gaussian distribution and such in the random module.

You can easily do so by:

numpy.random.normal(loc=7, scale=1.0, size=None)


This will produce a normal distribution with μ=7 and σ2=1.0

def randlist(minn, maxn, goaln, countn):
nlist = []


Consider renaming this function to the distribution's name that you are looking for. Such as normal for a normal distribution. Rename minn and maxn to min_ or max_. Since you are trying to avoid clashes with the keywords, you could also try using synonyms such as low and high.

for i in range(0, countn):


range(countn) is enough to start the list from 0.

if len(nlist) > 10:
ave = numpy.mean(nlist)
if ave > goaln:
a = random.uniform(minn, goaln)
else:
a = random.uniform(goaln, maxn)
else:
a = random.uniform(minn, maxn)


Since you are adding the first 10 numbers randomly to the list, you can do so inside the nlist itself in the form of a list comprehension (see sample code below).

def weighted_distribution(low, high, ev, count, start=10):
result = [random.uniform(low, high) for i in range(start)]
for i in range(count-start):
if numpy.mean(result)> ev:
result.append(random.uniform(low, ev))
else:
result.append(random.uniform(ev, high))
return result


ev is the expected value for this distribution (mean).