基本绘图:箱线图

箱线图(Box Plot)是一种用于展示数据分布情况的统计图表,它通过五数概括法(最小值、第一四分位数、中位数、第三四分位数、最大值)以及异常值来简洁地描绘数据的分散性和偏态。Matplotlib 的 plt.boxplot() 函数提供了灵活的箱线图绘制能力。

📦 1. 基础箱线图

最简单的箱线图只需要传入一维数据:

import matplotlib.pyplot as plt
import numpy as np

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

plt.boxplot(data)
plt.title('基础箱线图')
plt.ylabel('数值')
plt.show()
✔️ 箱体表示四分位距,中间的线为中位数,须线延伸至非异常值范围,圆点为异常值。

🎨 2. 箱线图样式定制

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()

👥 3. 多组箱线图

传入多个数据集(列表的列表)可以绘制并列的箱线图:

# 生成三组数据
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 参数为每组数据指定标签。

⬅️ 4. 水平箱线图

通过 vert=False 将箱线图水平放置:

data = np.random.randn(100)

plt.boxplot(data, vert=False, patch_artist=True)
plt.title('水平箱线图')
plt.xlabel('数值')
plt.show()
✔️ 适用于展示较多组数据或标签较长的情况。

🔔 5. 凹口箱线图

使用 notch=True 可以绘制凹口箱线图,凹口部分表示中位数的置信区间(默认95%置信度),可用于比较中位数是否存在显著差异:

data = np.random.randn(100)

plt.boxplot(data, notch=True, patch_artist=True)
plt.title('凹口箱线图')
plt.show()
✔️ 如果两个箱的凹口不重叠,则有较强证据表明它们的中位数不同。

📊 6. 显示均值

使用 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)。

⚠️ 7. 控制异常值显示

通过 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()

📋 8. 从 pandas DataFrame 绘制箱线图

可以直接使用 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()
✔️ pandas 的 boxplot() 是基于 matplotlib 的封装,更简洁。

🎻 9. 扩展:小提琴图

小提琴图结合了箱线图和核密度估计,能更细致地展示数据分布。使用 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()
✔️ 小提琴图能显示数据分布的形状(如多峰)。

📌 10. 综合案例

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()
✔️ 箱线图和小提琴图结合使用,既能看统计量又能看分布形状。

💾 11. 保存图表

使用 savefig() 保存:

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

箱线图是探索数据分布和识别异常值的利器,掌握定制样式和多组对比后,你将能更全面地理解数据。下一章我们将学习热力图,用于展示矩阵数据和相关性。