The chi-square (χ²) distribution is fundamental in statistical testing, particularly for goodness-of-fit tests, independence tests, and confidence interval estimation. NumPy provides efficient methods to generate random samples from this distribution.
Using the Modern Generator API
The recommended approach uses NumPy's modern random generator:
import numpy as np
rng = np.random.default_rng(seed=42) # Optional seed for reproducibility
samples = rng.chisquare(df=3, size=5)
print(samples)Output:
[3.05543949 4.35892866 2.6205389 2.29722655 4.79524961]Understanding Degrees of Freedom
The df parameter (degrees of freedom) controls the distribution's shape:
import numpy as np
rng = np.random.default_rng()
low_df = rng.chisquare(df=1, size=5)
print(f"df=1: mean={low_df.mean():.2f}")
mid_df = rng.chisquare(df=5, size=5)
print(f"df=5: mean={mid_df.mean():.2f}")
high_df = rng.chisquare(df=30, size=5)
print(f"df=30: mean={high_df.mean():.2f}")Output:
df=1: mean=0.42
df=5: mean=5.07
df=30: mean=28.63Multi-dimensional Output
Generate matrices or higher-dimensional arrays of chi-square samples:
import numpy as np
rng = np.random.default_rng()
matrix = rng.chisquare(df=5, size=(3, 3))
print(matrix.shape) # (3, 3)
print(matrix)
tensor = rng.chisquare(df=10, size=(2, 3, 4))
print(tensor.shape) # (2, 3, 4)Output:
(3, 3)
[[ 2.68470397 4.50259988 3.39465421]
[ 5.0783715 1.16429817 3.38975043]
[ 5.70560665 1.39477394 14.24344514]]
(2, 3, 4)Visualizing Different Degrees of Freedom
Compare how the distribution shape changes with different df values:
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(seed=42)
fig, ax = plt.subplots(figsize=(10, 6))
degrees = [1, 2, 5, 10, 20]
colors = ['red', 'blue', 'green', 'orange', 'purple']
for df, color in zip(degrees, colors):
samples = rng.chisquare(df=df, size=10000)
ax.hist(samples, bins=100, density=True, alpha=0.5,
histtype='stepfilled', label=f'df={df}', color=color)
ax.set_xlabel('Value')
ax.set_ylabel('Density')
ax.set_title('Chi-Square Distribution for Various Degrees of Freedom')
ax.legend()
ax.set_xlim(0, 40)
plt.show()Statistical Properties
Verify theoretical properties with samples:
import numpy as np
rng = np.random.default_rng()
df = 10
samples = rng.chisquare(df=df, size=100000)
print(f"Degrees of freedom: {df}")
print(f"Theoretical mean: {df}")
print(f"Sample mean: {samples.mean():.2f}")
print(f"Theoretical variance: {2 * df}")
print(f"Sample variance: {samples.var():.2f}")Output:
Degrees of freedom: 10
Theoretical mean: 10
Sample mean: 9.99
Theoretical variance: 20
Sample variance: 19.82Practical Example: Chi-Square Test Simulation
Simulate the chi-square test statistic under the null hypothesis:
import numpy as np
def simulate_chi_square_test(observed, expected, n_simulations=10000):
"""Simulate chi-square test statistic distribution."""
rng = np.random.default_rng()
observed_stat = np.sum((observed - expected)**2 / expected)
df = len(observed) - 1
null_distribution = rng.chisquare(df=df, size=n_simulations)
p_value = np.mean(null_distribution >= observed_stat)
return observed_stat, p_value
observed = np.array([18, 22, 15, 20, 25, 20]) # Observed counts
expected = np.array([20, 20, 20, 20, 20, 20]) # Expected if fair
stat, p_val = simulate_chi_square_test(observed, expected)
print(f"Chi-square statistic: {stat:.2f}")
print(f"Simulated p-value: {p_val:.4f}")Output:
Chi-square statistic: 2.90
Simulated p-value: 0.7184Legacy API (For Reference)
The older API still works but is not recommended for new code:
import numpy as np
np.random.seed(42)
samples = np.random.chisquare(df=5, size=10)
rng = np.random.default_rng(42)
samples = rng.chisquare(df=5, size=10)Combining with SciPy for Full Analysis
For complete statistical analysis, combine NumPy sampling with SciPy:
import numpy as np
from scipy import stats
rng = np.random.default_rng()
df = 5
samples = rng.chisquare(df=df, size=10000)
x = np.linspace(0, 20, 100)
theoretical_pdf = stats.chi2.pdf(x, df)
p95 = stats.chi2.ppf(0.95, df)
print(f"95th percentile (theoretical): {p95:.2f}")
print(f"95th percentile (sample): {np.percentile(samples, 95):.2f}")Output:
95th percentile (theoretical): 11.07
95th percentile (sample): 11.06Parameters Reference
| Parameter | Description | Valid Values |
|---|---|---|
df |
Degrees of freedom | Positive number (> 0) |
size |
Output shape | int, tuple, or None |
Key Properties
| Property | Formula | Example (df=5) |
|---|---|---|
| Mean | df | 5 |
| Variance | 2 × df | 10 |
| Mode | max(df - 2, 0) | 3 |
| Skewness | √(8/df) | 1.26 |
Summary
Use np.random.default_rng().chisquare(df, size) to generate chi-square distributed random samples.
- The degrees of freedom parameter controls the distribution shape-lower values produce heavily right-skewed distributions, while higher values approach normality.
- This distribution is essential for hypothesis testing, particularly when comparing observed frequencies to expected frequencies.