2. 数据预处理与探索:数据清洗、缺失值处理、特征工程基础、数据分布可视化
大家好,我是老蓝。今天咱们聊聊数据预处理和探索。说实话,在量化风控这个领域,我见过太多人一上来就急着建模,结果模型跑出来一塌糊涂。为什么?因为数据没洗干净。我个人的习惯是,拿到数据后,至少花一半的时间在预处理上。你想想看,垃圾数据进去,再牛的算法也白搭。
2.1 数据清洗——先把脏东西筛掉
数据清洗,说白了就是把那些明显有问题的数据找出来处理掉。我在项目中遇到过最典型的例子:某个用户的年龄字段填了 200 岁,或者交易金额是负数。这些数据不处理,模型会学出什么鬼东西来?
常见的脏数据包括:
- 重复数据:同一个用户被录入了两次,特征完全一样
- 异常值:比如收入字段出现 999999999,明显是录入错误
- 格式不一致:手机号有的带区号,有的不带,有的中间有空格
- 逻辑矛盾:比如注册时间晚于当前时间,或者年龄和身份证号对不上
嗯,这里要注意:清洗不是一刀切。我曾经因为误删了一批看似异常但实际是真实的高风险交易数据,导致模型漏掉了关键信号。所以,清洗前一定要先理解业务含义。
2.2 缺失值处理——别让空值毁了你的模型
缺失值在风控数据里太常见了。用户可能没填职业信息,或者某个征信字段查不到。怎么处理?我一般分三步走:
- 先看缺失比例:如果某个字段缺失超过 70%,我建议直接扔掉。留着也没用,反而增加噪声。
- 再看缺失模式:是随机缺失,还是跟某些特征有关?比如高收入用户更不愿意填收入字段,这就是非随机缺失。
- 最后选填补方法:常用的有均值填补、中位数填补、或者用模型预测填补。
举个例子,假设我们有用户的收入数据,缺失了 20%。代码处理起来很简单:
import pandas as pd
import numpy as np
# 读取数据
df = pd.read_csv('user_data.csv')
# 查看缺失比例
print(df['income'].isnull().mean()) # 输出 0.2
# 用中位数填补
median_income = df['income'].median()
df['income'].fillna(median_income, inplace=True)
# 或者创建一个缺失标记
df['income_missing'] = df['income'].isnull().astype(int)
我个人更推荐第二种方式——保留缺失标记。因为缺失本身可能携带信息。
2.3 特征工程基础——从原始数据里挖金子
特征工程,说白了就是把原始数据变成模型能理解、能利用的形式。我常说一句话:特征决定了模型的上限,算法只是逼近这个上限。
在异常检测中,常用的特征工程方法包括:
- 数值特征标准化:比如把收入、年龄等缩放到 0-1 之间,避免量纲影响
- 类别特征编码:比如把「职业」这种文本字段转成数值,常用 one-hot 编码
- 时间特征提取:从交易时间中提取出「是否周末」「是否深夜」等特征
- 聚合特征:比如计算用户过去 30 天的平均交易金额、交易次数等
代码示例:标准化和编码
from sklearn.preprocessing import StandardScaler, OneHotEncoder
# 标准化数值特征
scaler = StandardScaler()
df['income_scaled'] = scaler.fit_transform(df[['income']])
# one-hot 编码类别特征
encoder = OneHotEncoder(sparse=False)
occupation_encoded = encoder.fit_transform(df[['occupation']])
2.4 数据分布可视化——用眼睛发现异常
数据可视化不是花架子,而是发现异常的最直观手段。我习惯在建模前先画几幅图,看看数据长什么样。
箱线图——一眼看出离群点
箱线图能展示数据的中位数、四分位数和离群点。如果某个点超出了箱线图的 whisker 范围,那它很可能就是异常值。
import matplotlib.pyplot as plt
import seaborn as sns
# 画箱线图
plt.figure(figsize=(10, 6))
sns.boxplot(x=df['income'])
plt.title('收入分布箱线图')
plt.show()
我在项目中遇到过:一个用户的交易金额是平均值的 100 倍,箱线图上一眼就看到了。这种点,要么是 VIP 大客户,要么就是异常交易。需要进一步核实。
直方图——看分布形态
直方图能告诉你数据是正态分布、偏态分布还是双峰分布。异常检测中,如果某个特征出现「长尾」,那尾巴上的点就值得关注。
# 画直方图
plt.figure(figsize=(10, 6))
sns.histplot(df['income'], bins=50, kde=True)
plt.title('收入分布直方图')
plt.show()
你想想看,如果大部分用户的收入集中在 5000-10000 之间,突然出现一个收入 100 万的用户,是不是很可疑?直方图就能帮你快速发现这种异常。
知识体系总览
下面这张图是我自己整理的,把本章的核心逻辑串起来了。你可以保存下来,做项目时对照着看。
这张图把整个流程串起来了:从原始数据开始,经过清洗、缺失值处理、特征工程,最后用可视化来验证。每一步都环环相扣,缺一不可。
好了,这一章的内容就到这里。数据预处理和探索是异常检测的基石,打好基础,后面的建模才能事半功倍。记住:花在数据上的时间,永远不会白费。
公众号:蓝海资料掘金营,微信deep3321