BrooklynSon
BrooklynSon

Reputation: 2103

Python Random Number Generator within a normal distribution with Min and Max values

In passing someone had suggested to me that I could use half normal distribution in python to set min and max points using 0 to infinity: halfnorm.rvs()

The 0 seems to cut off the min, however I have no idea what to do with the infinity.

I would like to do a number generator from 0 - 15 within a normal distribution, but having a hard time finding a function that doesn't go over the max or below the min due to the nature of distribution limits.

Upvotes: 2

Views: 3559

Answers (3)

keen21
keen21

Reputation: 1

I recently ran in to a similar issue.

To get around this and keep my min/max in reasonable bounds I just created some if statements to catch any numbers that went above the real min and max.

if value <0:
    value = abs(value)
elif value >15:
    value - 15 = diff
    value = 15-diff

This was close enough for me.

Upvotes: -1

dankal444
dankal444

Reputation: 4148

I had just answered similar question here. I'll copy answer here as I think this question title is much more informative:

You can use uniform distribution with boundaries "translated" from normal to uniform space (using error function) and convert it to normal distribution using inverse error function.

import matplotlib.pyplot as plt
import numpy as np
from scipy import special

mean = 0
std = 7
min_value = 0
max_value = 15

min_in_standard_domain = (min_value - mean) / std
max_in_standard_domain = (max_value - mean) / std

min_in_erf_domain = special.erf(min_in_standard_domain)
max_in_erf_domain = special.erf(max_in_standard_domain)

random_uniform_data = np.random.uniform(min_in_erf_domain, max_in_erf_domain, 10000)
random_gaussianized_data = (special.erfinv(random_uniform_data) * std) + mean
fig, axes = plt.subplots(1, 2, figsize=(12, 6))
axes[0].hist(random_uniform_data, 30)
axes[1].hist(random_gaussianized_data, 30)
axes[0].set_title('uniform distribution samples')
axes[1].set_title('erfinv(uniform distribution samples)')
plt.show()

enter image description here

Upvotes: 0

Dr. V
Dr. V

Reputation: 1914

I would try to use the beta-distribution: https://en.wikipedia.org/wiki/Beta_distribution. It's quite simple (e.g. to integrate) and capable of fitting typical reaction time distributions.

Now the question is how to sample this efficiently for fixed α and β parameters ... scipy has done it for us: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.beta.html

Edit: Motivated by the comment and curiosity, here an example, plotting the histogram of 10 samples á 1000 values:

from scipy.stats import beta
from numpy import histogram
import pylab

max_time = 3
min_time = 0.5

a, b = 2, 7
dist = beta(a, b)

for _ in range(10):
    sample = min_time + dist.rvs(size=1000) * (max_time - min_time)
    his, bins = histogram(sample, bins=20, density=True)
    pylab.plot(bins[:-1], his, ".")
pylab.xlabel("Reaction time [s]")
pylab.ylabel("Probability density [1/s]")
pylab.grid()
pylab.show()

enter image description here

Upvotes: 2

Related Questions