3. 数据准备与清洗:保单数据字段说明与预处理
数据准备与清洗是精算建模中最耗时但最关键的一环。原始保单数据通常包含缺失值、异常记录和格式不一致问题,若不经处理直接输入模型,会导致规则命中率计算偏差、模型过拟合甚至业务决策失误。本节将系统讲解保单核心字段、缺失值处理策略以及异常值识别与剔除方法。
3.1 保单数据核心字段说明
精算模型通常依赖以下核心字段进行规则命中率分析。下表列出各字段的名称、数据类型、业务含义及典型取值范围:
| 字段名称 | 数据类型 | 业务含义 | 典型取值范围 / 示例 |
|---|---|---|---|
| 保单号 | 字符串 | 唯一标识每张保单 | POL202310001 – POL202312999 |
| 年龄 | 整数 | 被保险人投保时的周岁年龄 | 18 – 65(常规重疾/寿险) |
| 性别 | 字符串 | 被保险人性别 | 男 / 女 |
| 保额 | 浮点数 | 保单的基本保险金额(万元) | 10.0 – 200.0 |
| 缴费期限 | 整数 | 保费缴纳的年数 | 1(趸交)、5、10、15、20、30 |
| 保险期限 | 整数 | 保障持续的年数 | 1(一年期)、10、20、30、终身(标记为99) |
| 年缴保费 | 浮点数 | 每年应缴保费金额(元) | 500 – 50000 |
| 健康告知等级 | 整数 | 核保后的健康风险分级 | 1(标准体)、2(次标准体)、3(拒保体) |
| 投保渠道 | 字符串 | 保单销售渠道 | 个险 / 银保 / 网销 / 经代 |
| 是否承保 | 布尔 | 最终承保结果 | True / False |
字段对齐提示:在规则命中率分析中,年龄、保额和健康告知等级是命中率最高的三个驱动字段。建议在清洗阶段优先保证这三个字段的完整性和准确性。
3.2 缺失值处理策略
缺失值在真实保单数据中普遍存在,原因包括录入遗漏、系统迁移丢失或字段非必填。不同字段的缺失机制不同,需采用差异化处理策略:
3.2.1 缺失值分类与处理方法
| 缺失类型 | 常见字段 | 推荐处理方法 | 处理依据 |
|---|---|---|---|
| 完全随机缺失 | 投保渠道、缴费期限 | 删除记录(若缺失率 < 5%)或众数填充 | 缺失与数据本身无关,删除不影响分布 |
| 随机缺失 | 年缴保费、保额 | 回归插补 / 多重插补(MICE) | 可利用年龄、性别、缴费期限预测 |
| 非随机缺失 | 健康告知等级 | 单独编码为“未知”类别,保留缺失信息 | 缺失本身可能隐含高风险信号 |
| 结构性缺失 | 保险期限(终身标记) | 保留特殊标记值(如99),不填充 | 属于业务定义,非数据错误 |
3.2.2 缺失值处理代码示例(Python)
import pandas as pd
import numpy as np
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
# 加载原始保单数据
df = pd.read_csv('policy_data_raw.csv')
# 1. 完全随机缺失:投保渠道缺失率 < 5%,直接删除
df.dropna(subset=['投保渠道'], inplace=True)
# 2. 随机缺失:年缴保费使用多重插补
imputer = IterativeImputer(max_iter=10, random_state=42)
df[['年缴保费', '年龄', '保额', '缴费期限']] = imputer.fit_transform(
df[['年缴保费', '年龄', '保额', '缴费期限']]
)
# 3. 非随机缺失:健康告知等级单独编码
df['健康告知等级'] = df['健康告知等级'].fillna('未知')
# 4. 结构性缺失:保险期限终身标记保留
# 无需处理,99 为有效业务值
print(f"缺失值处理完成,剩余记录数:{len(df)}")
注意:切勿对所有缺失字段统一使用均值填充。均值填充会压缩数据方差,导致规则命中率阈值计算失真,尤其对保额、年缴保费等右偏分布字段影响严重。
3.3 异常值识别与剔除
异常值指明显偏离正常业务逻辑或统计分布的数据点。在精算场景中,异常值可能来自录入错误、系统bug或欺诈行为,必须识别并处理。
3.3.1 异常值识别方法对比
| 方法 | 适用字段 | 判定规则 | 优点 | 缺点 |
|---|---|---|---|---|
| Z-Score 法 | 年龄、缴费期限 | |Z| > 3 视为异常 | 简单快速,适合正态分布 | 对偏态分布不敏感 |
| IQR 四分位法 | 保额、年缴保费 | Q1 - 1.5*IQR 或 Q3 + 1.5*IQR 之外 | 稳健,不受极端值影响 | 对厚尾分布可能过度剔除 |
| 业务规则法 | 年龄、保额、健康告知 | 年龄 < 0 或 > 120;保额 < 0 | 直接反映业务逻辑 | 无法识别统计异常 |
| 孤立森林 | 多字段联合 | 异常得分 > 阈值 | 适合高维异常检测 | 计算成本高,需调参 |
3.3.2 异常值剔除流程
推荐采用“业务规则 + IQR 法”组合策略,分步执行:
- 业务规则过滤:剔除年龄 < 0 或 > 120、保额 <= 0、年缴保费 <= 0 的记录。
- 单变量 IQR 检测:对保额、年缴保费分别计算 Q1、Q3 和 IQR,标记超出 1.5 倍 IQR 的记录。
- 联合异常判定:若某条记录在 2 个及以上字段被标记为异常,则予以剔除;仅单字段异常则保留并做 Winsorize 截尾处理。
- 记录剔除日志:保存被剔除记录的保单号和原因,便于后续审计。
实战经验:在某次重疾险规则命中率分析中,原始数据包含 12 万条保单。经异常值识别后,发现约 3.2% 的记录存在保额异常(如保额 9999 万元,明显为录入错误)。剔除后模型命中率 AUC 从 0.72 提升至 0.79,提升效果显著。
3.4 数据清洗流程总览
下图展示了从原始保单数据到清洗后数据的完整处理流程,包含字段校验、缺失值处理和异常值剔除三个核心阶段:
3.5 清洗后数据质量检查清单
完成清洗后,建议按以下清单逐项验证数据质量,确保后续建模的可靠性:
- 完整性检查:所有核心字段(年龄、性别、保额、缴费期限)缺失率是否为 0%。
- 唯一性检查:保单号字段是否存在重复值,重复记录需去重或合并。
- 范围检查:年龄是否在 18–65 区间内;保额是否在 10–200 万之间;缴费期限是否在 {1,5,10,15,20,30} 集合中。
- 逻辑一致性检查:年缴保费 × 缴费期限 不应超过保额的一定比例(如 30%),否则可能存在录入错误。
- 分布形态检查:绘制保额、年缴保费的直方图,确认清洗后分布未出现异常断点或尖峰。
自动化建议:将上述检查清单编写为 Python 单元测试(pytest),每次数据更新后自动运行,确保清洗流程的稳定性和可复现性。