0

I've used random.normal() in the past to generate a single number who, if called multiple times, in aggregate would create a bell curve distribution. What I'm trying to do now is to create the opposite / inverse, where the distribution is biased towards the extremes within a range? There are built in functions in excel that seem to do what I want. Is there a way to do it in python? Thank you

SP00N
  • 25
  • 7

3 Answers3

1

It appears you want a distribution with an "upside-down bell curve" compared to the normal distribution. If so, then the following method implements this distribution via rejection sampling and a modified version of the standard normal distribution. 'x0' and 'x1' are the ranges of numbers to generate.

def invertedNormal(x0, x1):
  # Get the ends of the PDF (the bounding
  # box will cover the PDF at the given range)
  x0pdf = 1-math.exp(-(x0*x0))
  x1pdf = 1-math.exp(-(x1*x1))
  ymax = max(x0pdf, x1pdf)
  while True:
    # Choose a random x-coordinate
    x=random.random()*(x1-x0)+x0
    # Choose a random y-coordinate
    y=random.random()*ymax
    # Return x if y falls within PDF
    if y < 1-math.exp(-(x*x)):
      return x
Peter O.
  • 32,158
  • 14
  • 82
  • 96
0

You'd have to decide which probability distribution to use.

If you want to use pure Python, without external dependencies, check which distributions are available in the Random module: https://docs.python.org/3/library/random.html

For example you might use a Beta distribution with parameters (0.5, 0.5): https://docs.python.org/3/library/random.html#random.betavariate

See the Wikipedia page for beta distribution to understand the parameters: https://en.wikipedia.org/wiki/Beta_distribution

For advanced use, the external package scipy is the usual way to access probability distributions within Python: https://docs.scipy.org/doc/scipy/reference/stats.html

wjakobw
  • 525
  • 1
  • 4
  • 11
0

It sounds like what you are wanting is to shift the distribution the the edge of the range, and wrap around?

Something like this could do what you're looking for:

num = (random.normal() + 0.5) % 1

Luke Storry
  • 6,032
  • 1
  • 9
  • 22