箱线图(Box Plot)是一种用于展示数据分布情况的统计图表,它通过五数概括法(最小值、第一四分位数、中位数、第三四分位数、最大值)以及异常值来简洁地描绘数据的分散性和偏态。Matplotlib 的 plt.boxplot() 函数提供了灵活的箱线图绘制能力。
最简单的箱线图只需要传入一维数据:
import matplotlib.pyplot as plt
import numpy as np
# 生成随机数据
data = np.random.randn(100) # 100个标准正态分布数据
plt.boxplot(data)
plt.title('基础箱线图')
plt.ylabel('数值')
plt.show()
boxplot() 支持丰富的参数来控制箱线图的外观:
| 参数 | 说明 | 示例 |
|---|---|---|
patch_artist | 是否填充箱体颜色 | patch_artist=True |
boxprops | 箱体属性字典 | boxprops={'facecolor':'lightblue','edgecolor':'blue'} |
whiskerprops | 须线属性 | whiskerprops={'color':'black','linestyle':'--'} |
capprops | 须线端帽属性 | capprops={'color':'red','linewidth':2} |
medianprops | 中位数线属性 | medianprops={'color':'red','linewidth':2} |
flierprops | 异常值点属性 | flierprops={'marker':'o','markerfacecolor':'red','markersize':5} |
data = np.random.randn(100)
plt.boxplot(data,
patch_artist=True,
boxprops={'facecolor': 'lightblue', 'edgecolor': 'blue'},
whiskerprops={'color': 'gray', 'linestyle': '--'},
capprops={'color': 'black', 'linewidth': 2},
medianprops={'color': 'red', 'linewidth': 2},
flierprops={'marker': 'o', 'markerfacecolor': 'red', 'markersize': 4})
plt.title('定制样式的箱线图')
plt.show()
传入多个数据集(列表的列表)可以绘制并列的箱线图:
# 生成三组数据
np.random.seed(42)
data1 = np.random.normal(0, 1, 100) # 均值为0,标准差1
data2 = np.random.normal(1, 1.5, 100) # 均值为1,标准差1.5
data3 = np.random.normal(2, 2, 100) # 均值为2,标准差2
plt.boxplot([data1, data2, data3], labels=['组A', '组B', '组C'])
plt.title('多组箱线图')
plt.ylabel('数值')
plt.show()
labels 参数为每组数据指定标签。通过 vert=False 将箱线图水平放置:
data = np.random.randn(100)
plt.boxplot(data, vert=False, patch_artist=True)
plt.title('水平箱线图')
plt.xlabel('数值')
plt.show()
使用 notch=True 可以绘制凹口箱线图,凹口部分表示中位数的置信区间(默认95%置信度),可用于比较中位数是否存在显著差异:
data = np.random.randn(100)
plt.boxplot(data, notch=True, patch_artist=True)
plt.title('凹口箱线图')
plt.show()
使用 showmeans=True 显示均值(默认不显示),并可通过 meanprops 定制样式:
data = np.random.randn(100)
plt.boxplot(data, showmeans=True, meanline=True, # meanline=True 用线条表示均值
meanprops={'color': 'blue', 'linestyle': '-', 'linewidth': 2})
plt.title('显示均值的箱线图')
plt.show()
meanline=True)。通过 showfliers 隐藏异常值,或用 sym 参数改变异常值符号:
data = np.random.randn(100)
plt.subplot(1,2,1)
plt.boxplot(data, sym='*') # 异常值显示为星号
plt.title('异常值为星号')
plt.subplot(1,2,2)
plt.boxplot(data, showfliers=False) # 隐藏异常值
plt.title('隐藏异常值')
plt.tight_layout()
plt.show()
可以直接使用 pandas 的 boxplot() 方法,非常方便:
import pandas as pd
import numpy as np
# 创建DataFrame
df = pd.DataFrame({
'类别A': np.random.randn(100),
'类别B': np.random.randn(100) + 1,
'类别C': np.random.randn(100) * 2
})
df.boxplot(grid=False, patch_artist=True)
plt.title('pandas DataFrame 箱线图')
plt.show()
boxplot() 是基于 matplotlib 的封装,更简洁。小提琴图结合了箱线图和核密度估计,能更细致地展示数据分布。使用 plt.violinplot() 绘制:
data = [np.random.normal(0, 1, 100),
np.random.normal(1, 1.5, 100),
np.random.normal(2, 2, 100)]
plt.violinplot(data, positions=[1,2,3], showmeans=True, showmedians=True)
plt.title('小提琴图')
plt.xlabel('组别')
plt.ylabel('数值')
plt.show()
import matplotlib.pyplot as plt
import numpy as np
# 生成三组具有不同分布的数据
np.random.seed(42)
data1 = np.random.normal(0, 1, 200) # 正态分布
data2 = np.random.uniform(-2, 2, 200) # 均匀分布
data3 = np.concatenate([np.random.normal(-2, 0.5, 100),
np.random.normal(2, 0.5, 100)]) # 双峰分布
data = [data1, data2, data3]
labels = ['正态分布', '均匀分布', '双峰分布']
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 箱线图
axes[0].boxplot(data, labels=labels, patch_artist=True,
boxprops={'facecolor': 'lightblue'})
axes[0].set_title('箱线图')
# 小提琴图
parts = axes[1].violinplot(data, showmeans=True, showmedians=True)
# 为小提琴图设置颜色
for pc in parts['bodies']:
pc.set_facecolor('lightcoral')
pc.set_alpha(0.7)
axes[1].set_xticks([1,2,3])
axes[1].set_xticklabels(labels)
axes[1].set_title('小提琴图')
plt.tight_layout()
plt.show()
使用 savefig() 保存:
plt.savefig('boxplot.png', dpi=300, bbox_inches='tight') # PNG
plt.savefig('boxplot.pdf', bbox_inches='tight') # 矢量PDF
箱线图是探索数据分布和识别异常值的利器,掌握定制样式和多组对比后,你将能更全面地理解数据。下一章我们将学习热力图,用于展示矩阵数据和相关性。