📊 Python数据分析可视化:一眼看穿数据分布的“箱线图”全指南(附可运行代码)
❝摘要:平均值会骗人,但箱线图不会。在数据分析中,如何快速识别异常值?如何比较不同组数据的真实分布?箱线图(Boxplot)是你必须掌握的利器。本文提供零错误、可直接运行的Python代码,带你从原理到实战,彻底搞定箱线图。
🌟 为什么你需要箱线图?
在处理数据集时,我们往往只关注平均值(Mean)。但平均值很容易受到极端值(Outliers)的影响。比如,马云和你平均一下,你也是亿万富翁,但这显然不能代表你的真实财富水平。
箱线图(Boxplot),又称盒须图,由美国数学家John Tukey于1977年发明。它不仅能展示数据的中心趋势和离散程度,还能直观地标记出异常值。它是探索性数据分析(EDA)阶段最不可或缺的图表之一。
箱线图的“五数概括”
下界 (Lower Bound / Lower Adjacent Value) :
- 注意:它通常 (Q1 - 1.5 × IQR),但不一定是整个数据集的绝对最小值。
- 定义:数据中25%的位置,即有25%的数据小于此值。
- 定义:数据的中间值。相比平均值,它受极端值影响更小,更能代表数据的“中心”。
- 定义:数据中75%的位置,即有75%的数据小于此值。
上界 (Upper Bound / Upper Adjacent Value) :
- 注意:它通常 (Q3 + 1.5 × IQR),但不一定是整个数据集的绝对最大值。
🔴 关于异常值 (Outliers):位于上界之上或下界之下的独立数据点,被定义为异常值。它们通常以圆点、菱形或星号单独标记在须的外部。
🛠️ 实战:用Python绘制箱线图
我们将使用Python中最流行的两个绘图库:Matplotlib 和 Seaborn。注:以下代码已在 Python 3.8+ 环境中测试通过,确保无报错。
1. 准备环境与数据
首先,确保你安装了必要的库:
pip install pandas matplotlib seaborn
接下来是核心代码。为了避免常见的“数组长度不匹配”错误,我们采用动态获取长度的方式来构建数据,确保逻辑严密。
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as sns# --- 设置绘图风格与中文显示 ---# 设置样式sns.set_style("whitegrid")# 设置中文字体 (Windows常用'SimHei', Mac常用'Arial Unicode MS'或'Heiti TC')# 如果运行出现乱码,请根据操作系统修改下面的字体名称plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans'] plt.rcParams['axes.unicode_minus'] = False# 解决负号显示问题# --- 生成模拟数据 ---np.random.seed(42) # 固定随机种子,保证每次运行结果一致# A组:正常分布,均值50,标准差10data_A = np.random.normal(loc=50, scale=10, size=100) # B组:均值更高,波动更大data_B = np.random.normal(loc=60, scale=15, size=100) # C组:包含明显的异常值# 95个正常数据 + 3个极大的异常值 (90, 95, 100)normal_part_C = np.random.normal(loc=45, scale=8, size=95)outliers_C = np.array([90, 95, 100])data_C = np.concatenate([normal_part_C, outliers_C])# --- 构建 DataFrame (关键步骤:确保长度一致) ---# 错误做法:手动写死数字,容易算错长度导致报错# 正确做法:使用 len() 动态获取每个数组的长度df = pd.DataFrame({'数值': np.concatenate([data_A, data_B, data_C]),'类别': ['A组'] * len(data_A) + ['B组'] * len(data_B) + ['C组'] * len(data_C)})# 打印前几行检查数据print("数据预览:")print(df.head())print(f"\n数据总行数: {len(df)}")print(f"C组数据长度: {len(data_C)} (应包含95个正常值+3个异常值)")
2. 绘制基础箱线图
使用 Seaborn 一行代码即可生成专业图表。
plt.figure(figsize=(10, 6))# 绘制箱线图# palette设置颜色,linewidth设置箱体线条宽度sns.boxplot(x='类别', y='数值', data=df, palette='Set2', linewidth=1.5)plt.title('不同组别销售数据分布对比', fontsize=16, pad=20)plt.xlabel('组别', fontsize=12)plt.ylabel('销售额', fontsize=12)plt.grid(axis='y', linestyle='--', alpha=0.5) # 添加横向网格线plt.show()
👀 读图指南:
- 箱体(蓝色/绿色方块):包含了中间50%的数据。箱子越扁,说明数据越集中;箱子越高,说明数据波动越大。
- 中间横线:中位数。注意观察C组,中位数明显低于A组和B组,说明其整体水平较低。
- 上下须(Whiskers):延伸至非异常值的最大/最小范围。
- 菱形点(C组上方):这就是代码中生成的 90, 95, 100 三个异常值。Seaborn 自动根据统计学规则(通常是1.5倍IQR)将它们识别并单独标记出来。
3. 进阶:箱线图 + 小提琴图 (Violin Plot)
如果你想同时看到数据的概率密度分布形状(比如数据是双峰的还是单峰的),可以将箱线图叠加在小提琴图上。这是目前高端分析报告中最流行的画法。
plt.figure(figsize=(10, 6))# 第一步:画小提琴图 (显示分布密度)# inner=None 表示不显示内部细节,留给箱线图展示sns.violinplot(x='类别', y='数值', data=df, palette='pastel', inner=None, alpha=0.7)# 第二步:叠加箱线图# width设窄一点,color设为黑色或深色,facecolor设为none使其透明sns.boxplot(x='类别', y='数值', data=df, width=0.15, color='black', boxprops={'facecolor':'none', 'linewidth': 1.5}, medianprops={'color': 'red', 'linewidth': 2}) # 将中位数线设为红色突出显示plt.title('组合图表:小提琴图(分布) + 箱线图(统计量)', fontsize=16, pad=20)plt.xlabel('组别', fontsize=12)plt.ylabel('数值', fontsize=12)plt.show()