3. 数据准备与清洗:多源数据整合与质量治理
赔付率异常归因的起点是数据。精算模型对数据质量高度敏感,脏数据会直接导致归因方向错误。本章聚焦保单、理赔、财务三大核心数据源的整合策略与常见质量问题的清洗方案。
3.1 三大数据源的结构与关键字段
赔付率计算依赖三张基础表:保单表(承保信息)、理赔表(出险与赔付记录)、财务表(已赚保费与已发生损失)。下表列出各表的核心字段与关联键:
| 数据源 | 核心字段 | 关联键 | 典型粒度 |
|---|---|---|---|
| 保单表 | 保单号、起保/终保日期、险种、保费、保额、渠道、地区 | 保单号 | 每张保单一条记录 |
| 理赔表 | 报案号、保单号、出险日期、立案日期、结案日期、赔付金额、未决金额 | 保单号 → 保单表 | 每案一条或多条(多次赔付) |
| 财务表 | 会计期间、保单号、已赚保费、已发生损失、IBNR、费用分摊 | 保单号 + 会计期间 | 每保单每期一条 |
精算提示: 保单号是三大数据源的核心关联键。若保单号在理赔表或财务表中缺失或格式不一致,将导致整条记录无法匹配,直接影响赔付率计算的分子或分母。
3.2 数据整合流程与常见问题
整合通常分为三步:字段对齐 → 键值匹配 → 聚合汇总。每一步都可能引入质量问题。
3.3 常见数据质量问题分类
根据项目经验,赔付率建模中高频出现的数据质量问题可归为以下五类:
| 问题类别 | 典型表现 | 影响环节 | 严重程度 |
|---|---|---|---|
| 缺失值 | 保单号为空、赔付金额为0或NULL | 匹配、聚合 | 高 |
| 重复记录 | 同一理赔案在财务表中出现多次 | 赔付率计算 | 高 |
| 格式不一致 | 日期格式混用、金额含逗号/货币符号 | 字段对齐 | 中 |
| 逻辑异常 | 出险日期早于起保日期、赔付金额大于保额 | 数据验证 | 高 |
| 孤儿数据 | 理赔记录找不到对应保单 | 匹配 | 中 |
避坑提醒: 理赔表中的“赔付金额”字段常混入“已决金额”和“未决金额”两种口径。未做区分直接求和,会导致赔付率虚高或虚低。建议在清洗阶段新增字段
pay_type 标记已决/未决。
3.4 清洗策略与代码实现
以下给出针对上述问题的标准化清洗流程,使用 Python 伪代码示意:
# 步骤1:字段对齐与格式统一
def align_fields(df_policy, df_claim, df_finance):
# 统一日期格式
df_policy['start_date'] = pd.to_datetime(df_policy['start_date'])
df_claim['loss_date'] = pd.to_datetime(df_claim['loss_date'])
# 统一金额字段,去除逗号与货币符号
df_finance['earned_premium'] = df_finance['earned_premium'].str.replace(',','').astype(float)
return df_policy, df_claim, df_finance
# 步骤2:键值清洗与匹配
def clean_keys(df_policy, df_claim):
# 保单号去空格、转大写
df_policy['policy_id'] = df_policy['policy_id'].str.strip().str.upper()
df_claim['policy_id'] = df_claim['policy_id'].str.strip().str.upper()
# 删除保单号为空的记录
df_policy = df_policy.dropna(subset=['policy_id'])
df_claim = df_claim.dropna(subset=['policy_id'])
# 左连接保留所有保单
df_merged = df_policy.merge(df_claim, on='policy_id', how='left')
return df_merged
# 步骤3:去重与逻辑校验
def dedup_and_validate(df):
# 按保单号+报案号去重,保留最新记录
df = df.drop_duplicates(subset=['policy_id', 'claim_id'], keep='last')
# 逻辑校验:出险日期不能早于起保日期
df = df[df['loss_date'] >= df['start_date']]
return df
3.5 数据质量监控指标
清洗完成后,建议建立持续监控机制,跟踪以下指标:
- 匹配率:理赔表与保单表成功匹配的记录占比,目标 ≥ 98%
- 缺失率:关键字段(保单号、赔付金额)缺失比例,目标 < 1%
- 重复率:同一保单-报案号组合出现次数 > 1 的比例,目标 < 0.5%
- 逻辑异常率:出险日期早于起保日期、赔付金额为负等异常占比,目标 < 0.1%
实战要点: 在精算模型中,数据清洗不是一次性工作。每次模型迭代前都应重新执行清洗流程,并记录清洗前后的记录数、赔付率变化,形成数据质量报告,作为模型假设的支撑依据。
3.6 整合后的数据表结构示例
清洗整合后的最终数据表应包含以下字段,用于后续赔付率计算与归因分析:
| 字段名 | 类型 | 说明 | 来源 |
|---|---|---|---|
| policy_id | string | 保单号(清洗后) | 保单表 |
| acc_period | string | 会计期间(YYYY-MM) | 财务表 |
| earned_premium | float | 已赚保费 | 财务表 |
| incurred_loss | float | 已发生损失(已决+未决) | 理赔表+财务表 |
| claim_count | int | 出险次数 | 理赔表 |
| loss_ratio | float | 赔付率 = incurred_loss / earned_premium | 计算字段 |
至此,数据准备与清洗阶段完成。下一阶段将基于清洗后的数据表,构建赔付率异常检测与归因模型。