理论基础:
均匀分布是连续型概率分布,若随机变量 ( X ) 在区间 ([a, b]) 上满足概率密度函数 ( f(x) = \frac{1}{b-a} ),则称 ( X ) 服从均匀分布,记作 ( X \sim U(a, b) )。其特点是变量在区间内每个点的概率密度相等,常用于模拟随机场景(如随机时间间隔、随机抽样)。
代码实现:
import numpy as np
import matplotlib.pyplot as plt
# 生成均匀分布数据
a, b, n = 0, 1, 20 # 区间[0,1],生成20个等距点
x = np.linspace(a, b, n) # 生成等差数据点
y = np.ones(n) / (b - a) # 均匀分布概率密度函数
# 绘制分布曲线(连续型)与离散点图
plt.figure(figsize=(8, 4))
plt.plot(x, y, 'b-', label='均匀分布密度函数')
plt.stem(x, y, 'r', markerfmt='ro', label='离散点表示')
plt.ylim(0, 1.5)
plt.xlabel('x')
plt.ylabel('概率密度')
plt.title('均匀分布 (U(0,1)) 概率密度函数')
plt.legend()
plt.show()
核心概念:
np.random.rand()
生成 ([0,1)) 区间连续均匀随机数,np.random.randint()
生成指定区间的离散整数随机数。np.random.seed(seed)
设置固定种子,确保结果可复现,便于代码调试和协作。代码示例:
# 生成单个随机实数
single_rand = np.random.rand(1) # 输出:array([0.1234])(示例值)
print(f"单个均匀随机实数:{single_rand[0]:.4f}")
# 生成10个随机数并可视化
np.random.seed(123) # 固定种子确保结果一致
rand_array = np.random.rand(10)
plt.figure(figsize=(10, 3))
plt.plot(range(10), rand_array, 'bo', linestyle='', label='随机数点')
plt.xlabel('样本索引')
plt.ylabel('随机数值')
plt.title('[0,1]区间均匀随机数分布')
plt.legend()
plt.show()
理论解析:
标准正态分布:均值 (\mu=0),标准差 (\sigma=1),概率密度函数为:
[
f(x) = \frac{1}{\sqrt{2\pi}} e{-\frac{x2}{2}}
]
曲线关于 (x=0) 对称,呈钟形,约68%数据在 ([-1, 1]),95%在 ([-2, 2]),99.7%在 ([-3, 3])(经验法则)。
分位数与概率计算:
pdf(z)
:计算 (z) 处的概率密度值ppf(q)
:计算累积概率 (q) 对应的分位数(如 (q=0.95) 对应单侧临界值)cdf(z)
:计算 (P(Z \leq z)) 的累积概率概率面积图函数:
from scipy import stats as st
def norm_prob_area(a, b):
"""绘制标准正态分布区间[a,b]的概率面积图"""
x = np.linspace(-4, 4, 400)
y = st.norm.pdf(x)
mask = (x >= a) & (x <= b)
p = st.norm.cdf(b) - st.norm.cdf(a)
plt.figure(figsize=(10, 5))
plt.plot(x, y, 'k-', label='标准正态分布')
plt.fill_between(x, y, where=mask, color='skyblue', alpha=0.5, label=f'P({a:.2f}≤Z≤{b:.2f})={p:.4f}')
plt.xlabel('z值')
plt.ylabel('概率密度')
plt.title('标准正态分布区间概率面积')
plt.legend()
plt.show()
print(f"区间[{a:.2f}, {b:.2f}]的概率:{p:.4f}(即{p*100:.2f}%)")
norm_prob_area(-1.96, 1.96) # 输出95%置信区间的经典临界值
实战应用:
代码对比:
# 标准正态分布随机数直方图(1000个样本)
np.random.seed(456)
z_std = np.random.normal(0, 1, 1000)
plt.figure(figsize=(12, 4))
plt.subplot(121)
plt.hist(z_std, bins=30, density=True, alpha=0.6, color='teal', label='样本直方图')
x_theory = np.linspace(-4, 4, 100)
y_theory = st.norm.pdf(x_theory)
plt.plot(x_theory, y_theory, 'r-', lw=2, label='理论密度曲线')
plt.title('标准正态随机数分布')
plt.legend()
# 对数正态分布转换演示
np.random.seed(15)
y_lognorm = np.random.lognormal(0, 1, 1000) # 均值0,标准差1的对数正态
z_lognorm = np.log(y_lognorm) # 转换后服从N(0,1)
plt.subplot(122)
sns.distplot(z_lognorm, hist=False, kde=True, color='orange', label='转换后正态分布')
plt.title('对数正态分布转换为正态分布')
plt.legend()
plt.tight_layout()
plt.show()
检验原理:
Q-Q图(分位数-分位数图)通过对比样本分位数与理论分位数的拟合程度判断正态性:
代码实现:
# 绘制Q-Q图
plt.figure(figsize=(12, 4))
plt.subplot(131)
st.probplot(X, plot=plt) # 正态数据Q-Q图(近似直线)
plt.title('正态数据Q-Q图')
plt.subplot(132)
st.probplot(Y, plot=plt) # 对数正态数据Q-Q图(上凸曲线)
plt.title('对数正态数据Q-Q图')
plt.subplot(133)
st.probplot(Z, plot=plt) # 转换后正态数据Q-Q图(恢复直线)
plt.title('转换后正态数据Q-Q图')
plt.tight_layout()
plt.show()
核心抽样方法:
代码实战:
import pandas as pd
# 读取学生数据(假设BSdata包含52个学生的身高、性别等信息)
BSdata = pd.read_excel('DaPy_data.xlsx', 'BSdata')
# 方法1:通过随机索引抽样(不放回)
np.random.seed(15)
sample_indices = np.random.randint(1, 53, 6) # 生成1-52之间的6个不重复整数
selected_students = BSdata.iloc[sample_indices]
# 方法2:直接使用pandas.sample()(默认不放回)
direct_sample = BSdata.sample(6, random_state=15) # 设置random_state确保复现
定理要点:
无论总体分布如何,当样本量 (n) 足够大时(通常 (n \geq 30)),样本均值 (\bar{X}) 的分布趋近于正态分布 (N(\mu, \sigma^2/n))。
模拟对比:
def clt_simulation(dist_type='normal', n=30, N=10000):
"""模拟中心极限定理:样本均值的分布"""
xbar = np.zeros(N)
for i in range(N):
if dist_type == 'normal':
data = np.random.normal(0, 1, n) # 正态总体
else:
data = np.random.uniform(0, 1, n) # 均匀总体(非正态)
xbar[i] = data.mean()
plt.figure(figsize=(10, 5))
sns.distplot(xbar, bins=50, kde=True, label=f'样本均值分布 (n={n})')
plt.xlabel('样本均值')
plt.title(f'中心极限定理模拟:{dist_type}总体')
plt.legend()
plt.show()
print(pd.DataFrame(xbar).describe().T[['mean', 'std']]) # 输出均值和标准差
# 正态总体模拟(n=30)
clt_simulation('normal')
# 均匀总体模拟(n=30,可见均值分布接近正态)
clt_simulation('uniform')
应用场景:
当总体标准差 (\sigma) 未知且样本量 (n) 较小时((n < 30)),样本均值的标准化统计量 (t = \frac{\bar{X} - \mu}{S/\sqrt{n}}) 服从自由度 (df = n-1) 的t分布。
曲线特性:
可视化对比:
x = np.linspace(-4, 4, 400)
yn = st.norm.pdf(x)
yt3 = st.t.pdf(x, 3)
yt10 = st.t.pdf(x, 10)
plt.figure(figsize=(8, 5))
plt.plot(x, yn, 'r-', lw=2, label='N(0,1)')
plt.plot(x, yt3, 'b--', lw=1.5, label='t(3)')
plt.plot(x, yt10, 'g-.', lw=1.5, label='t(10)')
plt.xlabel('t值')
plt.ylabel('概率密度')
plt.title('t分布与标准正态分布对比')
plt.legend()
plt.ylim(0, 0.45)
plt.show()
点估计 vs 区间估计:
方法 | 定义 | 示例 | 优点 | 缺点 |
---|---|---|---|---|
点估计 | 用单个值估计总体参数 | 样本均值 (\bar{X}) 估计 (\mu) | 简洁直观 | 未体现估计误差 |
区间估计 | 用区间[L, U]估计参数 | 95%置信区间 ([\bar{X}-1.96SE, \bar{X}+1.96SE]) | 量化不确定性 | 区间宽度依赖样本量 |
代码实现(身高数据区间估计):
def t_confidence_interval(data, confidence=0.95):
"""计算t分布置信区间"""
n = len(data)
mean = data.mean()
std = data.std(ddof=1) # 样本标准差(无偏估计)
se = std / np.sqrt(n)
df = n - 1
critical_val = st.t.ppf(1 - (1 - confidence)/2, df)
lower = mean - critical_val * se
upper = mean + critical_val * se
return (lower, upper)
# 计算身高均值的95%置信区间
height_data = BSdata['身高']
ci = t_confidence_interval(height_data)
print(f"身高均值的{95}%置信区间:[{ci[0]:.2f}, {ci[1]:.2f}]")
单样本t检验步骤:
可视化函数增强:
def ttest_visualization(X, mu=0):
"""绘制t检验拒绝域及置信区间"""
df = len(X) - 1
t_stat, p_val = st.ttest_1samp(X, mu)
t_abs = abs(t_stat)
alpha = 0.05
critical_t = st.t.ppf(1 - alpha/2, df)
x = np.linspace(-4, 4, 400)
y = st.t.pdf(x, df)
plt.figure(figsize=(10, 5))
plt.plot(x, y, 'k-', label=f't分布 (df={df})')
# 绘制拒绝域(双侧)
mask_left = x <= -critical_t
mask_right = x >= critical_t
plt.fill_between(x, y, where=mask_left, color='red', alpha=0.2, label=f'拒绝域 (α/2={alpha/2})')
plt.fill_between(x, y, where=mask_right, color='red', alpha=0.2)
# 绘制样本t值
plt.axvline(t_stat, color='blue', linestyle='--', label=f'样本t值: {t_stat:.3f}')
plt.axvline(-t_stat, color='blue', linestyle='--')
# 标注p值
plt.text(0, 0.1, f'p值: {p_val:.4f}', fontsize=12, ha='center')
plt.xlabel('t值')
plt.ylabel('概率密度')
plt.title(f'单样本t检验可视化 (μ0={mu})')
plt.legend()
plt.show()
ttest_visualization(BSdata['身高'], 166) # 检验身高均值是否为166
根据这章的学习,让我深刻体会到数据科学中理论与实践的紧密联结。通过代码实现概率分布的模拟、随机数生成与可视化,原本抽象的统计概念(如中心极限定理、t分布形态)变得直观可感——正态分布的钟型曲线在Q-Q图中化为笔直的参考线,假设检验的拒绝域通过概率密度图跃然眼前。我认识到,统计分析不仅是数学公式的推导,更是通过数据对话现实问题的思维方式。Python工具链(如numpy、scipy、matplotlib)在此过程中扮演了关键桥梁,让理论得以在代码中“活”起来:一个简单的ttest_1samp()函数背后,蕴含着抽样分布、显著性水平的复杂逻辑;而置信区间的计算则让我体会到用概率语言量化不确定性的精妙。这种“理论可视化、方法代码化”的学习路径,不仅深化了对统计本质的理解,更让我在数据建模的道路上多了份“知其然亦知其所以然”的底气。