Generating Random Numbers from Distributions

NumPy's random generator supports drawing samples from a wide variety of probability distributions. These include normal (Gaussian), binomial, Poisson, exponential, and many others—each useful for different modeling and simulation tasks.

Key Features of Distribution Sampling

  • Parametric control: Each distribution method accepts parameters like mean, standard deviation, rate, number of trials, and probabilities.
  • Support for scalars and arrays: Generate single samples or entire arrays with specified shapes.
  • Efficient and vectorized: Sampling is optimized for speed and works seamlessly with NumPy arrays.

Understanding how to use these distribution methods will help you model uncertainty, simulate data, and run probabilistic algorithms effectively.



Generate Samples from a Normal Distribution

The normal() method from NumPy's Generator draws random samples from a normal (Gaussian) distribution. This distribution is characterized by its mean (center) and standard deviation (spread).

Use this method when modeling real-world data that follows a bell-shaped curve, such as measurement errors, natural phenomena, or noise in machine learning.

python
import numpy as np

rng = np.random.default_rng()

# Generate a single random number from a normal distribution
# with mean=0 and standard deviation=1
single_sample = rng.normal(loc=0, scale=1)

# Generate a 1D array of 5 samples from a normal distribution
samples_array = rng.normal(loc=10, scale=2, size=5)

print("Single sample:", single_sample)
print("Array of samples:", samples_array)

How It Works:

  • loc is the mean of the distribution (default is 0).
  • scale is the standard deviation (default is 1).
  • size determines the shape of the returned output (omit for a scalar).
  • Samples are drawn from the distribution 𝒩(loc, scale²).

Output

Single sample: -0.2828633447096407
Array of samples: [12.48357077  9.30867849 13.23844269 17.61514928  8.82923313]

💡 Tip: Use rng.normal() to simulate noisy data, perform Monte Carlo experiments, or initialize weights in neural networks.


Generate Samples from a Uniform Distribution

The uniform() method generates random numbers from a uniform distribution, where each value in the specified range is equally likely to occur. This is useful when you need unbiased random values between two bounds.

The values are drawn from the half-open interval [low, high), meaning the lower bound is inclusive and the upper bound is exclusive.

python
import numpy as np

rng = np.random.default_rng()

# Generate a single uniform random number between 0 and 1
single_value = rng.uniform()

# Generate a single uniform random number between 5 and 15
bounded_value = rng.uniform(low=5, high=15)

# Generate a 1D array of 5 uniform samples between -1 and 1
array_values = rng.uniform(low=-1, high=1, size=5)

print("Single (0 to 1):", single_value)
print("Single (5 to 15):", bounded_value)
print("Array (-1 to 1):", array_values)

How It Works:

  • low is the inclusive lower bound of the interval (default is 0.0).
  • high is the exclusive upper bound of the interval (default is 1.0).
  • size defines the output shape. Omit it to return a single float.

Output

Single (0 to 1): 0.7341513195271063
Single (5 to 15): 10.492847038227985
Array (-1 to 1): [ 0.361  -0.874   0.145  -0.582   0.913]

💡 Tip: Use rng.uniform() when you need evenly distributed random numbers within a custom range, such as coordinates, random initialization, or test data.


Generate Samples from a Exponential Distribution

The exponential() method generates samples from an exponential distribution, which is commonly used to model the time between events in a Poisson process — such as waiting times or failure rates.

This distribution is defined by a single parameter: the scale, which is the inverse of the rate (λ). The probability density function (PDF) is given by:

f(x; λ) = λ * exp(-λx), where λ = 1 / scale and x ≥ 0

python
import numpy as np

rng = np.random.default_rng()

# Generate a single sample from an exponential distribution with scale = 1.0
single_sample = rng.exponential(scale=1.0)

# Generate 5 samples with scale = 2.0 (mean = 2)
array_samples = rng.exponential(scale=2.0, size=5)

print("Single sample:", single_sample)
print("Array of samples:", array_samples)

How It Works:

  • scale is the inverse of the event rate λ (default is 1.0).
  • size defines the shape of the output. Omit to return a single float.
  • All output values are non-negative (≥ 0).

Output

Single sample: 0.5874
Array of samples: [1.638 2.954 0.528 4.119 0.861]

💡 Tip: Use rng.exponential() to model waiting times, survival analysis, and time-to-event processes.


Generate Samples from a Binomial Distribution

The binomial() method draws samples from a binomial distribution. It models the number of successes in a fixed number of independent trials, where each trial has two possible outcomes (like success/failure or heads/tails), and the probability of success remains constant.

This distribution is ideal for simulating experiments like flipping a coin, passing a test, or manufacturing defects — where you count how many times something “succeeds” out of a total number of attempts.

python
import numpy as np

rng = np.random.default_rng()

# Simulate flipping a coin 10 times (probability of heads = 0.5)
single_result = rng.binomial(n=10, p=0.5)

# Simulate 5 such experiments
multiple_results = rng.binomial(n=10, p=0.5, size=5)

print("Single experiment result:", single_result)
print("Multiple experiment results:", multiple_results)

How It Works:

  • n is the number of trials (e.g., 10 coin flips).
  • p is the probability of success in each trial (e.g., 0.5 for heads).
  • size controls the number of samples to generate.
  • The result is the count of successes in each simulated experiment.

Output

Single experiment result: 6
Multiple experiment results: [5 4 7 6 3]

💡 Tip: Use binomial() to model real-world binary outcomes like pass/fail, yes/no, win/lose — where you're counting how often something happens out of a fixed number of chances.


Generate Samples from a Poisson Distribution

The poisson() method generates random numbers from a Poisson distribution. This distribution models the number of times an event occurs within a fixed interval of time or space, given a constant average rate.

It’s commonly used for modeling counts of rare events — like incoming emails per hour, customer arrivals, or the number of accidents at an intersection in a day.

python
import numpy as np

rng = np.random.default_rng()

# Generate a single Poisson-distributed value with lambda = 4
single_value = rng.poisson(lam=4)

# Generate an array of 5 Poisson-distributed samples
sample_array = rng.poisson(lam=4, size=5)

print("Single sample:", single_value)
print("Sample array:", sample_array)

How It Works:

  • lam (λ) is the expected number of occurrences (mean rate).
  • size specifies how many samples to generate (omit for a single value).
  • The output values are integers ≥ 0, representing event counts.

Output

Single sample: 3
Sample array: [2 4 6 3 5]

💡 Tip: Use rng.poisson() for modeling event frequencies, especially when events happen randomly but with a known average rate.


Frequently Asked Questions

How do I generate random numbers from a normal distribution in NumPy?

Use NumPy's random Generator method .normal(loc=0.0, scale=1.0, size=None) to generate samples from a normal distribution with specified mean and standard deviation.


What is the difference between np.random and the new Generator API?

The new Generator API provides better random number quality and more flexible methods compared to the older np.random module. It is recommended to use numpy.random.default_rng() to create a Generator instance.


Can I generate random numbers from other distributions like binomial or poisson?

Yes, the Generator API supports many distributions such as binomial, poisson, uniform, and exponential via methods like .binomial(), .poisson(), .uniform(), and .exponential().


How do I set a random seed for reproducible results?

Pass an integer seed to numpy.random.default_rng(seed) to create a reproducible Generator instance that produces the same sequence of random numbers on each run.


What is the recommended way to generate random numbers in NumPy?

Use numpy.random.default_rng() to create a Generator object and then call its distribution methods to generate random samples, which is the modern and preferred approach.



What's Next?

Up next, we'll explore Setting Random Seed for Reproducibility in NumPy — an essential technique to ensure consistent and repeatable results when generating random numbers. This topic is crucial for debugging, experiments, and sharing reproducible scientific code.