Distributions: normal, uniform, binomial
Generate realistic data from the three most useful probability distributions — normal (bell curve), uniform (flat) and binomial (count of successes).
randint and rand spread values evenly. Real cricket data is not even: most innings land near a batter's average and very big or very small scores are rare. To simulate data that behaves like the real world, you choose a probability distribution that matches the process.
Definition
A probability distribution describes how likely each possible value of a random variable is. NumPy's distribution functions draw random samples that follow that pattern.
The normal (Gaussian) distribution is a symmetric, bell-shaped distribution defined by its mean (centre) and standard deviation (spread). Values near the mean are most common; values far from it get rarer and rarer.
The uniform distribution gives every value in an interval
[low, high)the same probability — a flat shape.
The binomial distribution counts the number of successes in
nindependent yes/no trials, each with success probabilityp.
- Mean (μ,
loc) — the centre of the bell; most values cluster here. - Standard deviation (σ,
scale) — the typical distance from the mean. Bigger σ → wider, flatter bell. - 68–95–99.7 rule — in a normal distribution about 68% of values lie within 1σ of the mean, 95% within 2σ, 99.7% within 3σ.
- Trial — one yes/no experiment (win/lose a match, hit/miss a ball).
Why normal deserves special attention
Most real-world measurements cluster around an average with values further from the average becoming progressively rarer: batting scores, human heights, exam marks, measurement errors. np.random.normal(mean, std, size) takes exactly the two numbers that describe such a bell curve. This makes it usually the right choice for simulating realistic human or natural data — randint or uniform spread values evenly, which is not how most real things behave. (The deep reason is the Central Limit Theorem: anything that is the sum of many small independent effects tends to become normal.)
text
normal uniform
▁▃▅▇█▇▅▃▁ ▇▇▇▇▇▇▇▇▇▇
rare ← mean → rare every value equally likelySyntax
python
np.random.normal(loc=0.0, scale=1.0, size=None)
np.random.uniform(low=0.0, high=1.0, size=None)
np.random.binomial(n, p, size=None)| Function | Parameter | Meaning | Default |
|---|---|---|---|
normal | loc | Mean (centre) of the bell curve | 0.0 |
normal | scale | Standard deviation (spread); must be ≥ 0 | 1.0 |
uniform | low | Lower bound (inclusive) | 0.0 |
uniform | high | Upper bound (exclusive) | 1.0 |
binomial | n | Number of trials (int ≥ 0) | — required |
binomial | p | Probability of success in each trial, 0 to 1 | — required |
| all | size | Output shape (int or tuple) | None → one value |
Note:
np.random.normal(0, 1, size)is the same distribution asnp.random.randn(size), andnp.random.uniform(0, 1, size)is the same asnp.random.rand(size).
Example — normal: realistic batting scores
python
import numpy as np
np.random.seed(42)
scores = np.random.normal(loc=35, scale=12, size=8)
print(scores.round(1))
big = np.random.normal(35, 12, size=100_000)
print("mean:", big.mean().round(2), " std:", big.std().round(2))
within1 = np.mean((big > 23) & (big < 47))
within2 = np.mean((big > 11) & (big < 59))
print(f"within 1 std: {within1:.3f}")
print(f"within 2 std: {within2:.3f}")text
[41. 33.3 42.8 53.3 32.2 32.2 54. 44.2]
mean: 35.01 std: 12.01
within 1 std: 0.682
within 2 std: 0.954How it works: with 100,000 samples the sample mean and std match the loc and scale we asked for, and the 68–95 rule appears on its own. np.mean(boolean_array) gives the fraction of True values.
Tip: a normal distribution has no hard limits, so it can produce negative runs. For counts or scores, clip and round:
np.clip(x, 0, None).round().astype(int).
Example — uniform: any value in a range equally likely
python
np.random.seed(42)
sr = np.random.uniform(low=110, high=180, size=6)
print(sr.round(1))
big = np.random.uniform(110, 180, size=100_000)
print("min:", big.min().round(2), " max:", big.max().round(2), " mean:", big.mean().round(2))text
[136.2 176.6 161.2 151.9 120.9 120.9]
min: 110.0 max: 180.0 mean: 144.96All strike rates fall between 110 and 180 and the mean sits in the middle, (110 + 180) / 2 = 145. Use uniform when you only know the bounds, not a typical value.
Example — binomial: wins in a season
python
np.random.seed(42)
# 14 matches, each won with probability 0.6 -> how many wins in a season?
wins = np.random.binomial(n=14, p=0.6, size=8)
print("wins in 8 simulated seasons:", wins)
seasons = np.random.binomial(14, 0.6, size=100_000)
print("average wins:", seasons.mean().round(2))
print("P(8+ wins, playoff):", np.mean(seasons >= 8).round(3))text
wins in 8 simulated seasons: [ 9 5 7 8 10 10 11 6]
average wins: 8.4
P(8+ wins, playoff): 0.693How it works: each value is "how many of 14 coin-flips (biased 60/40) came up heads". The expected value is n × p = 14 × 0.6 = 8.4, exactly what we see. Counting how often wins >= 8 estimates the playoff probability — a full season simulator in three lines.
With n=1 a binomial is a single coin toss (a Bernoulli trial):
python
np.random.seed(42)
toss = np.random.binomial(n=1, p=0.5, size=10) # 1 = heads
print(toss)text
[0 1 1 1 0 0 0 1 1 1]Comparison — which distribution should I use?
| Distribution | Shape | Values | Parameters | IPL example |
|---|---|---|---|---|
normal | bell | any real number | mean, std | runs per innings, player heights |
uniform | flat | real numbers in [low, high) | low, high | random strike rate between bounds, ball speed range |
binomial | discrete hump | integers 0 … n | n trials, p | wins in 14 matches, wickets in 6 deliveries |
randint | flat (integers) | integers low … high−1 | low, high | dice, random match number |
choice(p=…) | any custom | items you list | weights | ball outcomes: dot/1/4/6/W |
Other distributions you will meet later: poisson (events per interval — sixes per match), exponential (waiting time), lognormal (prices, salaries).
Common mistakes
- ❌ Passing the variance as
scale. ✅scaleis the standard deviation (σ), not σ². - ❌ Using
uniformfor human-like data (heights, scores). ✅ Usenormal— real data clusters around a mean. - ❌ Forgetting that normal can go negative. ✅
np.clip(..., 0, None). - ❌
binomial(14, 60). ✅pis a probability:0.6.
Interview tip
Q: Why is the normal distribution so common in data science? A: Because of the Central Limit Theorem — quantities that are the sum or average of many small independent effects tend to be normally distributed. Many statistical tests and ML models assume normality, so it is the default model for continuous natural data.
Key points to remember
- A probability distribution describes how likely each value is; NumPy can sample from many of them.
- normal(loc, scale, size) gives a bell curve: loc = mean, scale = standard deviation.
- In a normal distribution ~68% of values lie within 1 std of the mean and ~95% within 2 std.
- Normal is the right default for realistic natural data; uniform and randint spread values evenly.
- uniform(low, high, size) makes every value in [low, high) equally likely.
- binomial(n, p, size) counts successes in n yes/no trials; its mean is n × p.
- Clip and round normal samples when values must be non-negative whole numbers.
Try it yourself
Normal vs uniform: where do values land?
Season simulator with binomial
Practice: realistic innings
Revision Flashcards
Tap a card to flip it and see the answer.
