如何用Matplotlib实现68-95-99.7法则的正态分布可视化标注?
实现正态分布68-95-99.7法则的Matplotlib可视化
问题描述
我已经用Matplotlib绘制了正态分布图表:
import matplotlib.pyplot as plt import numpy as np import math fig, ax = plt.subplots() ax.set_title('概率密度分布') ax.set_xlabel('x') ax.set_ylabel('f(x)') x = np.linspace(148, 200, 100) # X范围148到200 y = (1 / (5 * math.sqrt(2*math.pi))) * np.exp((-(x-178)**2) / (2*5**2)) ax.plot(x, y) plt.show()
现在需要在绘图区域内添加竖线、为内部区间着色,并在y=0的轴上添加对应标记。尝试用plt.axvline时,竖线会超出主绘图区域:
plt.axvline(x = 178, color = 'g', label = 'axvline - full height') plt.axvline(x = 178+5, color = 'b', label = 'axvline - full height') plt.axvline(x = 178-5, color = 'b', label = 'axvline - full height') plt.axvline(x = 178+5*2, color = 'r', label = 'axvline - full height') plt.axvline(x = 178-5*2, color = 'r', label = 'axvline - full height')
请问如何用Python的Matplotlib实现所需的68-95-99.7法则可视化效果?
解决方案
1. 控制竖线高度,避免超出绘图区域
axvline默认贯穿整个轴范围,要让竖线只到曲线高度,可直接用ax.plot绘制从(x值, 0)到(x值, 对应曲线y值)的线段,精准匹配曲线高度。
2. 为区间分层着色
用ax.fill_between函数为不同σ区间填充颜色,从最外层(±3σ)到最内层(±1σ)依次绘制,通过透明度区分层次,保证视觉上的叠加效果。
3. 添加x轴标记
在x轴下方对应σ位置添加LaTeX格式的数学标记,调整y坐标避免遮挡曲线,让标注更规范清晰。
完整实现代码
import matplotlib.pyplot as plt import numpy as np import math # 正态分布核心参数 mu = 178 sigma = 5 x = np.linspace(148, 200, 100) y = (1 / (sigma * math.sqrt(2*math.pi))) * np.exp((-(x - mu)**2) / (2*sigma**2)) fig, ax = plt.subplots(figsize=(10, 6)) ax.set_title('概率密度分布(68-95-99.7法则)') ax.set_xlabel('x') ax.set_ylabel('f(x)') ax.plot(x, y, color='black', linewidth=2) # 定义各区间的范围、填充色和透明度 intervals = [ (mu - 3*sigma, mu + 3*sigma, '#ffcccc', 0.2), # ±3σ 区间 (mu - 2*sigma, mu + 2*sigma, '#cceeff', 0.3), # ±2σ 区间 (mu - sigma, mu + sigma, '#ccffcc', 0.4) # ±1σ 区间 ] # 分层填充区间 for x_left, x_right, color, alpha in intervals: ax.fill_between(x, y, where=(x >= x_left) & (x <= x_right), color=color, alpha=alpha) # 定义函数获取对应x值的曲线y高度 def get_curve_y(x_val): return (1 / (sigma * math.sqrt(2*math.pi))) * math.exp((-(x_val - mu)**2) / (2*sigma**2)) # 绘制均值线(绿色) mu_y = get_curve_y(mu) ax.plot([mu, mu], [0, mu_y], color='green', linestyle='--', linewidth=2) # 绘制±1σ线(蓝色) sigma1_y = get_curve_y(mu + sigma) ax.plot([mu-sigma, mu-sigma], [0, sigma1_y], color='blue', linestyle='--', linewidth=1.5) ax.plot([mu+sigma, mu+sigma], [0, sigma1_y], color='blue', linestyle='--', linewidth=1.5) # 绘制±2σ线(红色) sigma2_y = get_curve_y(mu + 2*sigma) ax.plot([mu-2*sigma, mu-2*sigma], [0, sigma2_y], color='red', linestyle='--', linewidth=1.5) ax.plot([mu+2*sigma, mu+2*sigma], [0, sigma2_y], color='red', linestyle='--', linewidth=1.5) # 绘制±3σ线(深红色) sigma3_y = get_curve_y(mu + 3*sigma) ax.plot([mu-3*sigma, mu-3*sigma], [0, sigma3_y], color='#8b0000', linestyle='--', linewidth=1) ax.plot([mu+3*sigma, mu+3*sigma], [0, sigma3_y], color='#8b0000', linestyle='--', linewidth=1) # 添加x轴标记 ax.text(mu, -0.002, r'$\mu$', ha='center', fontsize=12) ax.text(mu-sigma, -0.002, r'$\mu-\sigma$', ha='center', fontsize=12) ax.text(mu+sigma, -0.002, r'$\mu+\sigma$', ha='center', fontsize=12) ax.text(mu-2*sigma, -0.002, r'$\mu-2\sigma$', ha='center', fontsize=12) ax.text(mu+2*sigma, -0.002, r'$\mu+2\sigma$', ha='center', fontsize=12) ax.text(mu-3*sigma, -0.002, r'$\mu-3\sigma$', ha='center', fontsize=12) ax.text(mu+3*sigma, -0.002, r'$\mu+3\sigma$', ha='center', fontsize=12) # 调整y轴下限,避免标记被截断 ax.set_ylim(bottom=-0.005) plt.show()
效果说明
- 竖线精准贴合曲线高度,不会超出绘图区域
- 区间填充从外到内叠加,层次清晰,符合68-95-99.7的概率占比逻辑
- x轴标记规范直观,不会遮挡曲线内容
内容的提问来源于stack exchange,提问作者Nadezhda GR
相关产品推荐
相关产品推荐

