基本绘图:直方图

直方图用于展示连续数据的分布情况,将数据划分为若干个区间(bins),并用条形表示每个区间内数据的频数或频率。 Matplotlib 的 plt.hist() 函数提供了灵活的参数,可以轻松绘制直方图,并支持多组数据比较、密度曲线等高级功能。

📊 1. 基础直方图

最简单的直方图只需传入一维数据数组:

import matplotlib.pyplot as plt
import numpy as np

# 生成正态分布随机数据
data = np.random.randn(1000)  # 1000个标准正态分布数据

plt.hist(data)
plt.title('基础直方图')
plt.xlabel('数值')
plt.ylabel('频数')
plt.show()
✔️ 默认将数据分成10个bins。

🔢 2. 设置bins数量

bins 参数可以指定区间数量或具体的区间边界:

data = np.random.randn(1000)

plt.figure(figsize=(12, 4))

plt.subplot(1, 3, 1)
plt.hist(data, bins=5)
plt.title('bins=5')

plt.subplot(1, 3, 2)
plt.hist(data, bins=20)
plt.title('bins=20')

plt.subplot(1, 3, 3)
plt.hist(data, bins=np.arange(-4, 4.5, 0.5))  # 自定义区间边界
plt.title('自定义bins')

plt.tight_layout()
plt.show()
✔️ bins 可以是整数(区间个数),也可以是序列(区间边界)。

🎨 3. 直方图样式定制

hist() 支持多种样式参数:

参数说明示例
color柱体颜色color='steelblue'
edgecolor边框颜色edgecolor='black'
linewidth边框线宽linewidth=1.2
alpha透明度alpha=0.7
histtype直方图类型:'bar'(默认,条形)、'step'(轮廓)、'stepfilled'(填充轮廓)histtype='step'
示例:定制颜色和边框
data = np.random.randn(1000)

plt.hist(data, bins=30, color='lightcoral', edgecolor='darkred', linewidth=1.5, alpha=0.8)
plt.title('定制样式的直方图')
plt.show()

👥 4. 多组直方图并列

使用透明度叠加,或调整 histtypestep 绘制轮廓:

data1 = np.random.randn(1000)
data2 = np.random.randn(1000) + 1  # 偏移1个单位

plt.hist(data1, bins=30, alpha=0.5, label='数据集1')
plt.hist(data2, bins=30, alpha=0.5, label='数据集2')
plt.legend()
plt.title('两组直方图叠加')
plt.show()
✔️ 使用透明度可以清晰看到重叠部分。
使用轮廓样式
plt.hist(data1, bins=30, histtype='step', linewidth=2, label='数据集1')
plt.hist(data2, bins=30, histtype='step', linewidth=2, label='数据集2')
plt.legend()
plt.title('轮廓直方图')
plt.show()

🥞 5. 堆叠直方图

通过 stacked=True 将多组数据堆叠显示:

data1 = np.random.randn(1000)
data2 = np.random.randn(1000) + 2
data3 = np.random.randn(1000) - 1

plt.hist([data1, data2, data3], bins=30, stacked=True,
         label=['组1', '组2', '组3'], alpha=0.7)
plt.legend()
plt.title('堆叠直方图')
plt.show()
✔️ 传入数据列表,stacked=True 实现堆叠。

📈 6. 概率密度与累积分布

density=True 将纵坐标转换为概率密度,使总面积为1;cumulative=True 绘制累积直方图:

data = np.random.randn(1000)

plt.figure(figsize=(12, 4))

plt.subplot(1, 3, 1)
plt.hist(data, bins=30, density=True)
plt.title('概率密度直方图')
plt.ylabel('密度')

plt.subplot(1, 3, 2)
plt.hist(data, bins=30, cumulative=True)
plt.title('累积直方图')
plt.ylabel('累积频数')

plt.subplot(1, 3, 3)
plt.hist(data, bins=30, density=True, cumulative=True)
plt.title('累积概率密度')
plt.ylabel('累积概率')

plt.tight_layout()
plt.show()

📉 7. 叠加密度曲线

通常与 SciPy 或 seaborn 结合,这里演示使用 scipy 计算密度:

from scipy import stats

data = np.random.randn(1000)

# 绘制直方图(概率密度形式)
plt.hist(data, bins=30, density=True, alpha=0.6, color='steelblue', edgecolor='black')

# 拟合核密度估计
kde = stats.gaussian_kde(data)
x = np.linspace(data.min(), data.max(), 200)
plt.plot(x, kde(x), 'r-', linewidth=2, label='核密度估计')

plt.title('直方图 + 密度曲线')
plt.legend()
plt.show()
✔️ density=True 使直方图与密度曲线量纲一致。

🔲 8. 二维直方图

使用 plt.hist2d() 展示两个变量的联合分布:

x = np.random.randn(5000)
y = np.random.randn(5000) * 0.5 + x

plt.hist2d(x, y, bins=40, cmap='Blues')
plt.colorbar(label='频数')
plt.title('二维直方图')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()
✔️ cmap 指定颜色映射,colorbar 显示颜色条。

📦 9. 获取直方图数据

hist() 返回三个对象:n (频数/密度), bins (区间边界), patches (条形对象列表),可用于进一步定制:

data = np.random.randn(1000)
n, bins, patches = plt.hist(data, bins=20, color='skyblue', edgecolor='black')

# 找到频数最高的条形并改变颜色
max_idx = np.argmax(n)
patches[max_idx].set_facecolor('red')

plt.title('高亮频数最高的条形')
plt.show()
✔️ 通过 patches 可以单独修改每个条形的属性。

📌 10. 综合案例

# 生成三组数据:正态分布、偏态分布、双峰分布
np.random.seed(42)
data1 = np.random.randn(1000)
data2 = np.random.exponential(1, 1000) * 2
data3 = np.concatenate([np.random.randn(500) - 2, np.random.randn(500) + 2])

plt.figure(figsize=(10, 6))
plt.hist(data1, bins=30, alpha=0.5, density=True, label='正态分布')
plt.hist(data2, bins=30, alpha=0.5, density=True, label='指数分布')
plt.hist(data3, bins=30, alpha=0.5, density=True, label='双峰分布')

plt.title('不同分布对比直方图 (概率密度)')
plt.xlabel('数值')
plt.ylabel('密度')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

💾 11. 保存图表

使用 savefig() 保存为图片:

plt.savefig('histogram.png', dpi=300, bbox_inches='tight')   # PNG
plt.savefig('histogram.pdf', bbox_inches='tight')            # 矢量PDF

直方图是探索数据分布的基础工具,通过调整bins、叠加密度曲线、使用二维直方图,可以深入洞察数据特征。下一章我们将学习箱线图的绘制,用于展示数据的分散情况。