Matplotlib 直方图(Histogram)完全指南
直方图是 分布分析、概率密度、数据探索 的核心工具。本教程带你从入门到 发表级,掌握 基础直方图、密度图、堆叠、分组、双峰检测、误差棒、累积直方图、2D 直方图、艺术风格、交互式 等全部技巧。
一、基本直方图
import matplotlib.pyplot as plt
import numpy as np
# 生成正态分布数据
data = np.random.randn(1000)
plt.hist(data)
plt.show()
二、核心参数详解
plt.hist(data,
bins=30, # 柱子数量或边界
range=None, # 数据范围
density=False, # 是否归一化为概率密度
cumulative=False, # 累积直方图
color='skyblue', # 颜色
edgecolor='black', # 边框
alpha=0.7, # 透明度
histtype='bar', # 类型:'bar', 'step', 'stepfilled'
label='数据')
三、常用 bins 设置
| 类型 | 代码 | 说明 |
|---|---|---|
| 整数 | bins=30 | 30个等宽柱 |
| 列表 | bins=[0, 1, 2, 3, 5] | 自定义边界 |
| 自动 | bins='auto' | 推荐,自动优化 |
| Sturges | bins='sturges' | 小数据集 |
| Scott | bins='scott' | 理论最优 |
plt.hist(data, bins='auto', color='lightgreen', edgecolor='black')
四、概率密度图(归一化)
plt.hist(data, bins=30, density=True, alpha=0.7, color='steelblue', edgecolor='navy')
plt.ylabel('概率密度')
plt.title('归一化直方图')
plt.show()
density=True→ 面积和为 1
五、叠加正态分布曲线
from scipy import stats
mu, sigma = np.mean(data), np.std(data)
x = np.linspace(data.min(), data.max(), 100)
normal_pdf = stats.norm.pdf(x, mu, sigma)
plt.hist(data, bins=30, density=True, alpha=0.7, color='skyblue', edgecolor='black', label='直方图')
plt.plot(x, normal_pdf, 'r-', linewidth=2, label=f'正态分布\nμ={mu:.2f}, σ={sigma:.2f}')
plt.legend()
plt.show()
六、堆叠直方图(Stacked)
data1 = np.random.normal(0, 1, 1000)
data2 = np.random.normal(2, 1.5, 1000)
plt.hist([data1, data2], bins=30, stacked=True,
color=['skyblue', 'lightcoral'], edgecolor='black',
label=['组1', '组2'])
plt.legend()
plt.show()
七、分组直方图(并列)
plt.hist(data1, bins=30, alpha=0.7, color='skyblue', label='组1', edgecolor='black')
plt.hist(data2, bins=30, alpha=0.7, color='lightcoral', label='组2', edgecolor='black')
plt.legend()
plt.show()
八、水平直方图
plt.hist(data, bins=30, orientation='horizontal', color='purple', alpha=0.7)
plt.xlabel('频数')
plt.ylabel('值')
plt.show()
九、阶梯直方图(Step)
plt.hist(data, bins=30, histtype='step', linewidth=2, color='red')
plt.hist(data, bins=30, histtype='stepfilled', alpha=0.3, color='orange')
plt.show()
十、累积直方图
plt.hist(data, bins=30, cumulative=True, density=True,
color='green', edgecolor='darkgreen', linewidth=1.5)
plt.ylabel('累积概率')
plt.title('累积分布函数 (CDF)')
plt.show()
十一、2D 直方图(热力图)
x = np.random.randn(1000)
y = 1.5 * x + np.random.randn(1000)
plt.hist2d(x, y, bins=30, cmap='plasma')
plt.colorbar(label='频数')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('2D 直方图')
plt.show()
十二、误差棒直方图(带置信区间)
# 模拟多组实验数据
experiments = [np.random.normal(0, 1, 100) for _ in range(10)]
means = [np.mean(exp) for exp in experiments]
stds = [np.std(exp) for exp in experiments]
x_pos = np.arange(len(means))
plt.bar(x_pos, means, yerr=stds, capsize=5,
color='lightblue', edgecolor='navy', alpha=0.8)
plt.xlabel('实验编号')
plt.ylabel('均值')
plt.title('多组实验均值 ± 标准差')
plt.show()
十三、完整专业示例(论文级)
import matplotlib.pyplot as plt
import numpy as np
from scipy import stats
plt.style.use('seaborn-v0_8')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 生成双峰数据
np.random.seed(42)
data_bimodal = np.concatenate([
np.random.normal(-2, 1, 600),
np.random.normal(3, 1.5, 400)
])
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6))
# === 左图:密度直方图 + KDE ===
n, bins, patches = ax1.hist(data_bimodal, bins=50, density=True,
alpha=0.6, color='#1f77b4', edgecolor='white', linewidth=0.5)
# 添加核密度估计(KDE)
from scipy.stats import gaussian_kde
kde = gaussian_kde(data_bimodal)
x_kde = np.linspace(data_bimodal.min(), data_bimodal.max(), 200)
ax1.plot(x_kde, kde(x_kde), 'r-', linewidth=2.5, label='KDE 估计')
# 正态分布对比
mu, sigma = np.mean(data_bimodal), np.std(data_bimodal)
x_norm = np.linspace(data_bimodal.min(), data_bimodal.max(), 200)
ax1.plot(x_norm, stats.norm.pdf(x_norm, mu, sigma), 'k--', linewidth=1.5, label=f'正态拟合\nμ={mu:.2f}, σ={sigma:.2f}')
ax1.set_title('双峰分布分析', fontsize=16, fontweight='bold', pad=15)
ax1.set_xlabel('测量值', fontsize=12)
ax1.set_ylabel('概率密度', fontsize=12)
ax1.legend(fontsize=10)
ax1.grid(True, alpha=0.3, linestyle='--')
# === 右图:累积分布 + 分位数标注 ===
ax2.hist(data_bimodal, bins=50, cumulative=True, density=True,
color='#ff7f0e', edgecolor='white', alpha=0.8, linewidth=0.5)
# 添加分位数线
q25, q50, q75 = np.percentile(data_bimodal, [25, 50, 75])
for q, label, color in zip([q25, q50, q75], ['Q1', '中位数', 'Q3'], ['green', 'red', 'purple']):
ax2.axvline(q, color=color, linestyle='--', linewidth=2)
ax2.text(q, 0.9, f'{label}: {q:.2f}', color=color, fontweight='bold',
ha='center', va='bottom', bbox=dict(boxstyle="round", facecolor='white', alpha=0.8))
ax2.set_title('累积分布函数 (CDF)', fontsize=16, fontweight='bold', pad=15)
ax2.set_xlabel('测量值', fontsize=12)
ax2.set_ylabel('累积概率', fontsize=12)
ax2.grid(True, alpha=0.3, linestyle='--')
# 总标题
fig.suptitle('Matplotlib 直方图专业分析示例', fontsize=18, fontweight='bold', y=1.02)
plt.tight_layout()
plt.savefig('histogram_pro.png', dpi=300, bbox_inches='tight', facecolor='white')
plt.show()
十四、直方图速查表(收藏用)
# 基础
plt.hist(data, bins=30)
# 密度图
plt.hist(data, density=True, alpha=0.7)
# 堆叠
plt.hist([d1, d2], stacked=True)
# 并列
plt.hist(d1, alpha=0.7); plt.hist(d2, alpha=0.7)
# 阶梯
plt.hist(data, histtype='step', linewidth=2)
# 累积
plt.hist(data, cumulative=True, density=True)
# 2D
plt.hist2d(x, y, bins=30, cmap='hot')
# 自动bins
plt.hist(data, bins='auto')
十五、常见问题解决
| 问题 | 解决方案 |
|---|---|
| 柱子太密/太稀 | bins='auto' 或手动设置 |
| 看不到分布形状 | density=True + 叠加 KDE |
| 颜色重叠 | alpha=0.6 + edgecolor='white' |
| 2D 颜色条太小 | plt.colorbar(shrink=0.8) |
| 保存裁剪 | plt.savefig(..., bbox_inches='tight') |
十六、推荐风格模板
| 场景 | 推荐设置 |
|---|---|
| 论文 | 密度图 + KDE + 白边 |
| PPT | 彩色柱 + 透明度 |
| 探索分析 | bins='auto' + 阶梯线 |
| 双变量 | hist2d + plasma 热图 |
十七、添加统计信息框
mean = np.mean(data)
std = np.std(data)
text = f'均值: {mean:.2f}\n标准差: {std:.2f}\n样本数: {len(data)}'
plt.hist(data, bins=30, color='lightblue', edgecolor='black', alpha=0.7)
plt.text(0.95, 0.95, text, transform=plt.gca().transAxes,
verticalalignment='top', horizontalalignment='right',
bbox=dict(boxstyle="round", facecolor='wheat', alpha=0.8))
plt.show()
官方文档
- Hist API:https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.hist.html
- 2D Hist:https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.hist2d.html
- 示例图库:https://matplotlib.org/stable/gallery/statistics/histogram_features.html
总结:三步打造专业直方图
# 1. 绘制密度直方图
n, bins, patches = plt.hist(data, bins='auto', density=True, alpha=0.7, edgecolor='white')
# 2. 叠加KDE曲线
kde = gaussian_kde(data)
x = np.linspace(min(data), max(data), 200)
plt.plot(x, kde(x), 'r-', linewidth=2)
# 3. 美化输出
plt.xlabel('值'); plt.ylabel('密度')
plt.title('分布分析')
plt.grid(True, alpha=0.3)
plt.savefig('hist.png', dpi=300, bbox_inches='tight')
一键生成密度直方图 + 正态曲线:
data = np.random.randn(1000)
plt.hist(data, bins=30, density=True, alpha=0.7, color='skyblue', edgecolor='black')
x = np.linspace(-4, 4, 100)
plt.plot(x, stats.norm.pdf(x), 'r-', linewidth=2)
plt.show()
需要我为你:
- 生成 10种经典直方图模板?
- 制作 Jupyter 直方图交互小工具(滑块调整
bins)? - 输出 LaTeX/PPT 可用代码?
告诉我你的需求!