3. 数据探索与可视化:使用Pandas进行数据概览、Matplotlib/Seaborn绘制分布图与箱线图识别异常
在坏样本归因任务中,数据探索与可视化是连接原始数据与特征工程的桥梁。本章将系统讲解如何利用 Pandas 进行高效的数据概览,并借助 Matplotlib 与 Seaborn 绘制分布图与箱线图,从而快速定位异常值与数据分布特征。
3.1 使用Pandas进行数据概览
Pandas 提供了丰富的方法来快速了解数据集的全貌,包括数据维度、列类型、缺失值分布以及基本统计量。
| 方法 | 功能描述 | 关键参数/输出 |
|---|---|---|
df.info() |
打印 DataFrame 的摘要信息 | 行数、列数、列数据类型、非空计数、内存使用 |
df.describe() |
生成数值型列的统计摘要 | 均值、标准差、最小值、四分位数、最大值 |
df.isnull().sum() |
统计每列的缺失值数量 | 返回 Series,索引为列名,值为缺失数 |
df.nunique() |
统计每列的唯一值数量 | 适用于类别型特征的基数检查 |
df.head() / df.sample() |
预览数据前几行或随机抽样 | 默认 head() 显示前5行 |
实战要点: 在坏样本场景中,务必先检查
df['label'].value_counts() 以确认正负样本比例。若坏样本占比低于 5%,后续可视化与建模需考虑采样或代价敏感策略。
import pandas as pd
# 加载数据
df = pd.read_csv('bad_sample_data.csv')
# 数据概览
print("=== 数据基本信息 ===")
df.info()
print("\n=== 数值列统计描述 ===")
print(df.describe())
print("\n=== 缺失值统计 ===")
print(df.isnull().sum())
print("\n=== 标签分布 ===")
print(df['label'].value_counts(normalize=True))
3.2 分布图:理解单变量分布
分布图用于观察单个特征的数值分布形态,帮助识别偏态、多峰以及潜在的异常值区间。Seaborn 的 histplot 和 kdeplot 是首选工具。
- 直方图 (Histogram):将数据分箱,展示每个箱内的样本频数。
- 核密度估计 (KDE):平滑的连续概率密度曲线,便于观察分布形状。
- 联合分布图 (JointPlot):同时展示两个变量的分布与散点关系。
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 绘制单变量分布图
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
# 直方图 + KDE
sns.histplot(df['feature_amount'], bins=50, kde=True, ax=axes[0])
axes[0].set_title('特征 amount 分布 (含KDE)')
# 按标签分组绘制KDE
sns.kdeplot(data=df, x='feature_amount', hue='label', fill=True, ax=axes[1])
axes[1].set_title('按标签分组的KDE分布')
plt.tight_layout()
plt.show()
识别异常信号: 若分布图在远离主体数据的位置出现孤立小峰,或 KDE 曲线出现长尾拖拽,通常意味着该特征中存在极端值或坏样本特有的分布偏移。
3.3 箱线图:识别异常值的标准工具
箱线图通过五数概括(最小值、Q1、中位数、Q3、最大值)直观展示数据分布,并将超出 1.5 倍 IQR 范围的点标记为异常值。
| 箱线图元素 | 含义 | 异常判定规则 |
|---|---|---|
| 箱体 (Box) | Q1 到 Q3 的范围,包含 50% 的数据 | — |
| 中位线 (Median) | 箱体内部的横线,表示第 50 百分位数 | — |
| 须 (Whisker) | 从箱体延伸至非异常值的最远点 | 上限 = Q3 + 1.5 * IQR;下限 = Q1 - 1.5 * IQR |
| 异常点 (Flier) | 超出须范围的点,以菱形标记 | 超出 1.5 倍 IQR 即为潜在异常 |
# 绘制箱线图
plt.figure(figsize=(10, 5))
sns.boxplot(data=df[['feature_amount', 'feature_age', 'feature_score']])
plt.title('多个特征的箱线图对比')
plt.xticks(rotation=45)
plt.show()
# 按标签分组绘制箱线图
plt.figure(figsize=(8, 4))
sns.boxplot(x='label', y='feature_amount', data=df)
plt.title('按标签分组的箱线图 (坏样本 vs 好样本)')
plt.show()
注意: 箱线图标记的异常值不一定是“坏样本”,它仅代表统计意义上的极端值。在坏样本归因中,需要结合业务逻辑判断:某些极端值可能是正常的高价值交易,而非欺诈或坏账。
3.4 数据探索与异常识别流程
下图展示了从原始数据到异常识别的完整可视化分析流程,帮助你在实战中建立系统性的探索路径。
3.5 实战案例:从可视化到异常标记
以下代码演示了如何结合分布图与箱线图的结果,对识别出的异常值进行标记,为后续的坏样本归因提供特征层面的证据。
# 基于箱线图规则标记异常
def mark_outliers_iqr(df, column):
Q1 = df[column].quantile(0.25)
Q3 = df[column].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
return ((df[column] < lower_bound) | (df[column] > upper_bound))
# 对关键特征标记异常
df['amount_outlier'] = mark_outliers_iqr(df, 'feature_amount')
df['score_outlier'] = mark_outliers_iqr(df, 'feature_score')
# 查看异常样本与坏样本的重叠情况
cross_tab = pd.crosstab(df['amount_outlier'], df['label'],
margins=True, margins_name='总计')
print("异常标记与标签的交叉表:")
print(cross_tab)
# 可视化异常样本的分布
plt.figure(figsize=(8, 4))
sns.scatterplot(data=df, x='feature_amount', y='feature_score',
hue='amount_outlier', style='label', alpha=0.6)
plt.title('异常标记与标签的散点分布')
plt.show()
关键洞察: 在坏样本归因项目中,可视化不是终点,而是特征工程的起点。通过分布图发现偏态分布后,可考虑对数变换或分箱;通过箱线图识别异常后,可构建“是否异常”的二值特征,或对极端值进行截断处理。