4. 精算数据预处理:数据清洗、缺失值处理、异常值检测、特征工程在精算中的应用

精算模型对数据质量高度敏感。原始业务数据通常包含重复记录、格式不一致、缺失字段、极端离群值以及冗余特征。本章聚焦于将原始数据转化为适合精算评分模型的结构化、高质量特征集,涵盖数据清洗、缺失值处理、异常值检测与特征工程四大核心环节。

4.1 数据清洗:精算数据的第一道防线

数据清洗的目标是消除不一致、重复和格式错误。精算数据常见问题包括:保单号重复、日期格式混乱、费率代码拼写错误、金额字段包含货币符号等。

清洗类型 典型问题 Python 处理方式
重复记录 同一保单号出现多次 df.drop_duplicates(subset='policy_id')
格式统一 日期列含 "2024-01-01" 与 "01/01/2024" pd.to_datetime(df['date'], format='mixed')
类别标准化 "Male" / "M" / "男" 混用 映射字典 + df['gender'].map(mapping_dict)
金额清洗 字段含 "$" 或 "," df['amount'].str.replace('[\$,]', '', regex=True).astype(float)
精算提示: 在清洗阶段保留原始数据副本,并记录每步转换逻辑。精算审计要求数据转换过程可追溯。
import pandas as pd

# 示例:清洗保费金额字段
df['premium_raw'] = df['premium_raw'].str.replace('[\$,]', '', regex=True)
df['premium'] = pd.to_numeric(df['premium_raw'], errors='coerce')

# 去除完全重复的保单记录
df_clean = df.drop_duplicates(subset=['policy_id', 'effective_date'])

4.2 缺失值处理:精算场景下的策略选择

精算数据缺失并非随机。例如,高保额保单的财务信息更完整,而小额保单常缺失收入字段。处理策略需结合缺失机制与业务含义。

注意: 精算模型中,直接删除含缺失值的记录可能导致选择偏差,尤其当缺失与风险水平相关时。

4.2.1 缺失机制分类

  • 完全随机缺失 (MCAR):缺失与数据本身无关,可直接删除或简单填充。
  • 随机缺失 (MAR):缺失依赖于其他观测变量,需借助模型填充。
  • 非随机缺失 (MNAR):缺失与缺失值本身相关,需引入外部信息或业务假设。

4.2.2 常用填充方法对比

方法 适用场景 精算注意事项
均值/中位数填充 连续变量,缺失率 < 5% 会压缩方差,低估风险波动
众数填充 分类变量,如婚姻状况 可能强化主导类别权重
前向/后向填充 时间序列精算数据 需确保时间顺序正确
KNN 填充 多维特征,缺失率 5%-20% 计算量大,需标准化
模型预测填充 缺失率 > 20%,有辅助变量 避免数据泄露,使用交叉验证
from sklearn.impute import KNNImputer

# 对数值型精算特征进行 KNN 填充
imputer = KNNImputer(n_neighbors=5)
df_filled = pd.DataFrame(
    imputer.fit_transform(df[['age', 'income', 'claim_count']]),
    columns=['age', 'income', 'claim_count']
)

4.3 异常值检测:识别精算极端风险

异常值在精算中可能代表欺诈、录入错误或真正的极端风险。检测方法需区分全局异常与局部异常。

精算异常值检测流程 原始精算数据 异常值检测方法选择 统计法 Z-Score / IQR 模型法 孤立森林 / LOF 业务规则法 精算阈值 / 监管红线 标记 / 修正 / 剔除

4.3.1 常用检测方法

  • Z-Score 法:假设正态分布,|Z| > 3 视为异常。适用于近似正态的精算指标如 BMI、年龄。
  • IQR 法:Q1 - 1.5×IQR 以下或 Q3 + 1.5×IQR 以上。对偏态分布更稳健,如赔付金额。
  • 孤立森林:基于随机切割的集成方法,适合高维精算特征。
  • 局部异常因子 (LOF):检测局部密度异常,适用于欺诈检测场景。
from sklearn.ensemble import IsolationForest

# 孤立森林检测异常赔付记录
iso_forest = IsolationForest(contamination=0.05, random_state=42)
df['anomaly_flag'] = iso_forest.fit_predict(df[['claim_amount', 'age', 'policy_tenure']])
# -1 表示异常,1 表示正常
df_anomalies = df[df['anomaly_flag'] == -1]

4.4 特征工程:精算领域知识的量化

特征工程是将精算业务经验转化为模型可理解数值变量的过程。好的特征能显著提升评分模型的区分度与稳定性。

4.4.1 精算特征构建策略

特征类型 示例 精算含义
聚合统计 过去 12 个月平均赔付金额 反映历史风险暴露
比率特征 赔付金额 / 已缴保费 损失率,核心精算指标
时间特征 保单生效天数、续保间隔 刻画客户生命周期
交叉特征 年龄 × 吸烟状态 捕捉交互效应
编码特征 职业风险等级 (1-5) 将类别转化为有序变量

4.4.2 特征变换与选择

  • 对数变换:对右偏分布(如赔付金额)取 log,使分布更接近正态。
  • 分箱:将连续变量(如年龄)划分为精算风险区间:18-25, 26-35, 36-50, 51-65, 65+。
  • WOE 编码:证据权重编码,常用于精算评分卡模型,将类别变量映射为对数赔率。
  • 特征选择:使用方差阈值、相关系数、互信息或 L1 正则化筛选重要特征。
精算特征工程流程 原始精算数据 特征构建 聚合 / 比率 / 交叉 特征变换 分箱 / 对数 / WOE 特征选择 筛选 / 降维 精算评分特征集 迭代优化
精算最佳实践: 特征工程完成后,使用 df.describe() 和 df['feature'].hist() 检查分布合理性。确保所有特征在业务上可解释,避免使用黑箱特征导致监管合规风险。
import numpy as np

# 构建损失率特征
df['loss_ratio'] = df['total_claim_amount'] / (df['earned_premium'] + 1e-6)

# 年龄分箱
bins = [18, 25, 35, 50, 65, 100]
labels = ['18-25', '26-35', '36-50', '51-65', '65+']
df['age_band'] = pd.cut(df['age'], bins=bins, labels=labels, right=False)

# 对数变换赔付金额
df['log_claim'] = np.log1p(df['claim_amount'])