Python实战:用NumPy和Matplotlib绘制标准正态分布曲线(附完整代码)
Python数据可视化实战:从零绘制标准正态分布曲线
在数据分析的世界里,正态分布就像是一把万能钥匙,几乎可以打开任何统计问题的大门。想象一下,你手头有一组数据,想要快速了解它的分布特征——这时候,绘制一条正态分布曲线就能帮你直观判断数据是否符合"钟形"规律。作为Python数据分析的入门必备技能,掌握用NumPy生成正态分布数据并用Matplotlib绘制曲线的方法,将为你的数据分析之旅打下坚实基础。
1. 理解正态分布:数据世界的通用语言
正态分布,这个由德国数学家高斯系统研究并推广的概率分布模型,在自然界和人类活动中无处不在。从一群人的身高分布到流水线产品的尺寸误差,从股票收益率到考试成绩,正态分布的身影随处可见。
正态分布的核心特征:
- 对称的钟形曲线,峰值位于均值处
- 均值(μ)决定分布中心位置
- 标准差(σ)决定曲线"胖瘦"(数据离散程度)
- 约68%数据落在μ±σ内,95%在μ±2σ内,99.7%在μ±3σ内
标准正态分布是μ=0、σ=1的特例,其概率密度函数简化为:
φ(z) = (1/√(2π)) * e^(-z²/2)这种标准化形式让不同量纲的数据可以放在同一尺度下比较,是统计检验的基础。
2. 环境准备:搭建Python数据分析工作站
工欲善其事,必先利其器。在开始绘制曲线前,我们需要配置好Python环境并安装必要的库。推荐使用Anaconda发行版,它集成了数据科学所需的绝大多数工具。
必备工具清单:
- Python 3.8+(建议3.10稳定版)
- NumPy(数值计算核心库)
- Matplotlib(数据可视化利器)
- SciPy(科学计算扩展库)
安装命令(已安装Anaconda可跳过):
pip install numpy matplotlib scipy验证安装是否成功:
import numpy as np import matplotlib.pyplot as plt from scipy.stats import norm print("所有库已就绪!")提示:使用Jupyter Notebook进行交互式编程体验更佳,可以实时看到图形输出
3. 生成正态分布数据:NumPy的随机魔法
NumPy的random模块提供了多种生成正态分布数据的方法,我们重点介绍两种最常用的方式。
3.1 生成普通正态分布数据
import numpy as np # 设置分布参数 mu = 175 # 均值(例如平均身高175cm) sigma = 10 # 标准差 # 生成10000个符合正态分布的随机数 data = np.random.normal(mu, sigma, 10000)参数说明:
- loc(μ):分布均值,决定曲线中心位置
- scale(σ):标准差,决定曲线宽度
- size:生成数据的数量
3.2 生成标准正态分布数据
标准正态分布(μ=0, σ=1)有专用生成方法:
std_data = np.random.standard_normal(10000)或者使用通用方法的特例:
std_data_alt = np.random.normal(0, 1, 10000)两种方法生成的数组在统计特性上完全一致,第一种方法执行效率略高。
数据验证技巧:
print(f"均值:{np.mean(std_data):.4f}") # 应接近0 print(f"标准差:{np.std(std_data):.4f}") # 应接近14. 绘制概率密度曲线:Matplotlib可视化艺术
有了数据后,让我们用Matplotlib绘制专业的正态分布曲线。这里介绍两种互补的可视化方法。
4.1 基础绘制方法
import matplotlib.pyplot as plt from scipy.stats import norm # 创建画布 plt.figure(figsize=(10, 6), dpi=100) # 生成理论上的标准正态分布曲线 x = np.linspace(-4, 4, 1000) # 在[-4,4]区间生成1000个点 y = norm.pdf(x, 0, 1) # 计算标准正态分布PDF值 # 绘制理论曲线 plt.plot(x, y, 'r-', lw=3, alpha=0.8, label='理论PDF') # 添加图形元素 plt.title('标准正态分布概率密度函数', fontsize=15) plt.xlabel('Z值', fontsize=12) plt.ylabel('概率密度', fontsize=12) plt.grid(True, linestyle='--', alpha=0.5) plt.legend(fontsize=12) plt.show()关键参数解析:
figsize:控制图形宽高(英寸)dpi:分辨率,影响输出质量linspace:在指定范围生成等间距点norm.pdf:计算正态分布概率密度函数值
4.2 直方图与曲线叠加
更直观的方式是将生成数据的直方图与理论曲线叠加:
plt.figure(figsize=(10, 6)) # 绘制生成数据的直方图 plt.hist(std_data, bins=50, density=True, alpha=0.6, color='g', label='随机样本') # 绘制理论曲线 x = np.linspace(-4, 4, 1000) plt.plot(x, norm.pdf(x), 'r-', lw=2, label='理论PDF') # 美化图形 plt.title('标准正态分布样本验证', fontsize=15) plt.xlabel('值', fontsize=12) plt.ylabel('密度', fontsize=12) plt.legend() plt.grid(True, linestyle=':', alpha=0.7) plt.show()直方图关键参数:
| 参数 | 说明 | 推荐值 |
|---|---|---|
| bins | 分箱数量 | 30-100 |
| density | 是否归一化 | True |
| alpha | 透明度 | 0.5-0.7 |
| color | 柱状图颜色 | 任何有效颜色 |
5. 高级定制技巧:打造出版级图表
要让你的图表脱颖而出,还需要掌握一些高级定制技巧。
5.1 多子图对比展示
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5)) # 第一个子图:不同均值的对比 for mu in [0, 2, -2]: x = np.linspace(-6, 6, 500) ax1.plot(x, norm.pdf(x, mu, 1), label=f'μ={mu}, σ=1') ax1.set_title('不同均值对比') ax1.legend() # 第二个子图:不同标准差的对比 for sigma in [0.5, 1, 2]: x = np.linspace(-6, 6, 500) ax2.plot(x, norm.pdf(x, 0, sigma), label=f'μ=0, σ={sigma}') ax2.set_title('不同标准差对比') ax2.legend() plt.tight_layout() plt.show()5.2 填充关键区域
突出显示特定概率区域能增强图表表现力:
plt.figure(figsize=(10, 6)) x = np.linspace(-4, 4, 1000) y = norm.pdf(x) plt.plot(x, y, 'b-') # 填充μ±σ区域(68.27%) x_fill1 = np.linspace(-1, 1, 100) plt.fill_between(x_fill1, norm.pdf(x_fill1), color='blue', alpha=0.3, label='μ±σ (68.27%)') # 填充μ±2σ区域(95.45%) x_fill2 = np.linspace(-2, 2, 100) plt.fill_between(x_fill2, norm.pdf(x_fill2), color='green', alpha=0.2, label='μ±2σ (95.45%)') plt.title('正态分布概率区域示意', fontsize=15) plt.legend() plt.grid(True) plt.show()5.3 添加注释和公式
在图表中直接显示数学公式和关键注释:
from matplotlib.patches import ArrowStyle plt.figure(figsize=(10, 6)) x = np.linspace(-4, 4, 1000) plt.plot(x, norm.pdf(x), 'k-') # 添加公式文本 plt.text(0, 0.1, r'$\phi(z) = \frac{1}{\sqrt{2\pi}}e^{-\frac{1}{2}z^2}$', fontsize=16, ha='center', bbox=dict(facecolor='white', alpha=0.8)) # 添加箭头注释 plt.annotate('拐点位置', xy=(1, norm.pdf(1)), xytext=(2, 0.2), arrowprops=dict(arrowstyle='->', connectionstyle='arc3'), fontsize=12, bbox=dict(facecolor='white', alpha=0.7)) plt.title('标准正态分布数学表达式', fontsize=15) plt.grid(True, linestyle=':') plt.show()6. 实战应用:正态性检验与数据转换
掌握了绘制方法后,让我们看看如何在实际数据分析中应用这些技能。
6.1 QQ图正态性检验
from scipy.stats import probplot plt.figure(figsize=(10, 6)) probplot(std_data, plot=plt) plt.title('QQ图 - 正态性检验', fontsize=15) plt.grid(True) plt.show()解读要点:
- 数据点越接近红色参考线,正态性越好
- 尾部偏离可能暗示数据存在偏态或异常值
6.2 数据标准化转换
将非标准正态数据转换为标准正态形式:
# 原始数据(假设符合正态分布但参数未知) raw_data = np.random.normal(100, 20, 1000) # 标准化转换 standardized = (raw_data - np.mean(raw_data)) / np.std(raw_data) # 验证转换效果 plt.figure(figsize=(12, 5)) plt.subplot(1, 2, 1) plt.hist(raw_data, bins=30, alpha=0.7) plt.title('原始数据分布') plt.subplot(1, 2, 2) plt.hist(standardized, bins=30, alpha=0.7) plt.title('标准化后分布') plt.show()6.3 实际案例:考试成绩分析
假设我们有一组考试成绩,想要分析其分布:
# 模拟考试成绩数据 scores = np.random.normal(75, 10, 500) scores = np.clip(scores, 0, 100) # 确保分数在0-100之间 # 绘制分布图 plt.figure(figsize=(10, 6)) plt.hist(scores, bins=20, density=True, alpha=0.7, label='实际分布') # 拟合正态曲线 mu, sigma = np.mean(scores), np.std(scores) x = np.linspace(0, 100, 500) plt.plot(x, norm.pdf(x, mu, sigma), 'r-', lw=2, label=f'拟合曲线\n(μ={mu:.1f}, σ={sigma:.1f})') plt.title('考试成绩分布分析', fontsize=15) plt.xlabel('分数', fontsize=12) plt.ylabel('密度', fontsize=12) plt.legend() plt.grid(True) plt.show()在实际项目中,我经常使用这种可视化方法快速评估数据分布特征。有一次分析用户停留时间数据时,发现原始数据右偏严重,通过对数转换后才接近正态分布——这种洞察只有通过可视化才能快速获得。
