3. 数据探索与可视化:加载行情数据、描述性统计、坏账率分布直方图、相关性热力图

在构建XGBoost坏账率哨兵模型之前,必须对原始行情数据进行系统性的探索与可视化分析。本章将引导你完成从数据加载、基础统计到分布特征与变量关系的全流程诊断,为后续特征工程与模型训练奠定可靠的数据基础。

3.1 加载行情数据

行情数据通常以CSV格式存储,包含时间戳、资产价格、交易量以及衍生指标。使用Pandas库加载数据时,需注意数据类型转换与缺失值标记。

import pandas as pd
import numpy as np

# 加载行情数据
df = pd.read_csv('market_data.csv', parse_dates=['timestamp'])

# 查看数据形状与前5行
print(f'数据集形状: {df.shape}')
print(df.head())
字段名 类型 说明
timestamp datetime 交易时间戳
close_price float 收盘价
volume int 成交量
volatility float 波动率(20日滚动)
default_flag int 坏账标签(0/1)
实践要点:加载后立即检查 df.info() 确认每列非空值与数据类型,避免后续计算因类型错误而中断。

3.2 描述性统计

描述性统计能够快速揭示数据的集中趋势、离散程度与分布形态,是发现异常值与数据倾斜的第一步。

# 生成描述性统计表
desc = df.describe().T
desc['skew'] = df.skew(numeric_only=True)
desc['kurtosis'] = df.kurtosis(numeric_only=True)
print(desc[['mean','std','min','25%','50%','75%','max','skew','kurtosis']])
指标 均值 标准差 最小值 25%分位 中位数 75%分位 最大值 偏度 峰度
close_price 152.34 45.21 78.10 118.50 148.70 182.90 267.40 0.32 -0.67
volume 2.15e6 1.87e6 1.20e4 6.80e5 1.62e6 3.01e6 9.85e6 1.74 3.82
volatility 0.023 0.015 0.004 0.012 0.019 0.031 0.089 1.21 1.95
default_flag 0.087 0.282 0.000 0.000 0.000 0.000 1.000 2.93 6.58
关键发现:坏账标签 default_flag 均值仅 0.087,偏度 2.93,峰度 6.58,呈现典型的类别不平衡特征。成交量与波动率均呈右偏分布,存在极端值,后续需考虑对数变换或分箱处理。

3.3 坏账率分布直方图

坏账率分布直方图直观展示正负样本的频数差异,帮助判断是否需要采用采样策略或调整损失函数权重。

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(8,5))
sns.histplot(data=df, x='default_flag', bins=2, discrete=True, shrink=0.6)
plt.xticks([0,1], ['正常 (0)', '坏账 (1)'])
plt.ylabel('样本数量')
plt.title('坏账率分布直方图')
plt.show()
坏账率分布直方图 正常 (0) 91.3% 坏账 (1) 8.7% 样本数量 坏账样本仅占 8.7% 需处理类别不平衡
注意:若坏账样本占比低于10%,直接使用原始数据训练XGBoost可能导致模型偏向多数类。建议在后续章节中采用 scale_pos_weight 参数或SMOTE过采样策略。

3.4 相关性热力图

相关性热力图用于量化各特征与坏账标签之间的线性关联强度,同时检测特征间的多重共线性问题。

# 计算相关系数矩阵
corr_matrix = df.corr(numeric_only=True)

# 绘制热力图
plt.figure(figsize=(10,8))
sns.heatmap(corr_matrix, annot=True, fmt='.2f', cmap='RdBu_r',
            center=0, square=True, linewidths=0.5)
plt.title('行情特征与坏账标签相关性热力图')
plt.tight_layout()
plt.show()
行情特征与坏账标签相关性热力图 close_price volume volatility default_flag close_price volume volatility default_flag 1.00 0.12 -0.08 -0.15 0.12 1.00 0.35 0.08 -0.08 0.35 1.00 0.42 -0.15 0.08 0.42 1.00 相关性强度: 强正相关 (0.4~0.5) 弱正相关 (0.0~0.2) 弱负相关 (-0.2~0.0) 自身相关 (1.00) volatility 与 default_flag 相关性最高 (0.42) volume 与 volatility 存在中等正相关 (0.35)

3.5 数据探索总结与行动清单

基于上述探索性分析,整理出以下关键结论与后续行动项:

  • 类别不平衡严重:坏账样本仅占8.7%,需在XGBoost中设置 scale_pos_weight = (正常样本数 / 坏账样本数) 或采用过采样方法。
  • 波动率是关键信号:volatility与坏账标签相关系数0.42,应作为重要特征保留,并考虑构造衍生特征如波动率突变率。
  • 成交量存在长尾分布:偏度1.74,峰度3.82,建议进行对数变换 np.log1p(volume) 以降低极端值影响。
  • 多重共线性风险低:特征间最高相关系数为0.35(volume vs volatility),未超过0.7阈值,暂不需要做特征删除。
  • 缺失值检查:描述性统计中未发现明显缺失,但仍需用 df.isnull().sum() 逐列确认。
下一步行动:完成数据探索后,进入第4章“特征工程与数据预处理”,对波动率、成交量等关键特征进行变换与标准化,并构造时间窗口聚合特征,为XGBoost模型提供高质量输入。