3. 特征缺失巡检指标定义

特征缺失是风控数据质量中最常见、破坏性最强的问题之一。缺失数据会导致模型输出偏差、规则失效、决策链路中断。本章定义六大核心巡检指标,作为后续缺失拦截策略的量化基础。

3.1 指标全景

六大指标从不同维度刻画特征缺失状态:

指标名称 英文别名 核心含义 监控目标
缺失率 Missing Rate 特征值为空或未采集的比例 识别数据采集失败
空值率 Null Rate 特征值为数据库 NULL 的比例 区分显式空与隐式空
零值率 Zero Rate 特征值为 0 的比例 区分真实零与缺失零
异常波动率 Anomaly Volatility 指标值在时间窗口内的突变程度 发现数据源异常
特征新鲜度 Feature Freshness 特征最近一次有效更新的时间差 监控数据时效性
特征覆盖率 Feature Coverage 特征在目标群体中的有效覆盖比例 评估特征可用性
实践要点:六大指标并非孤立使用。缺失率与空值率常联合分析,零值率需结合业务语义判断,异常波动率与特征新鲜度共同构成数据健康度的"双引擎"。

3.2 缺失率与空值率

缺失率是最基础的巡检指标,定义为特征值为空(包括 NULL、空字符串、占位符)的记录数占总记录数的比例。

缺失率 = (缺失记录数 / 总记录数) × 100%

空值率特指数据库层面显式 NULL 的比例。两者差异在于:空值率只统计 NULL,缺失率还包含业务层面的空(如空字符串 ''、占位符 '-999'、'N/A')。

对比维度 缺失率 空值率
统计口径 NULL + 空字符串 + 占位符 仅 NULL
业务含义 数据不可用 数据库未赋值
阈值建议 > 5% 触发预警 > 3% 触发预警
典型场景 用户主动未填字段 接口返回失败
常见陷阱:部分特征在业务上允许为空(如"配偶姓名"),此时缺失率高是正常现象。必须结合特征业务属性设定差异化阈值,不可一刀切。

3.3 零值率

零值率衡量特征值为 0 的记录占比。零值在风控中具有双重语义:可能是真实零(如"近 30 天逾期次数=0"),也可能是缺失零(如"未查询到数据,默认填 0")。

零值率 = (特征值为 0 的记录数 / 总记录数) × 100%

零值率异常升高通常意味着数据源将缺失值统一填充为 0,这会严重误导模型。建议将零值率与缺失率联合监控:

  • 缺失率低 + 零值率高:可能为真实零,需结合业务判断
  • 缺失率高 + 零值率同步升高:大概率是缺失被填充为 0,需立即拦截
  • 零值率突增 > 20%:触发数据质量告警

3.4 异常波动率

异常波动率检测特征值在时间窗口内的突变程度,用于发现数据源故障、上游接口变更或批量脏数据注入。

异常波动率 = |当前窗口统计值 - 历史窗口统计值| / 历史窗口统计值

常用统计量包括均值、中位数、标准差。波动率超过阈值(通常 30%~50%)即触发异常标记。

案例:某特征"近 7 天登录次数"的日均值长期稳定在 3.2 左右。某日突降至 0.8,异常波动率达 75%。排查发现上游埋点接口因版本升级导致数据丢失,及时拦截避免了模型评分偏移。

3.5 特征新鲜度

特征新鲜度衡量特征最近一次有效更新距离当前时间的间隔,单位通常为小时或天。新鲜度越差,特征越可能失效。

特征新鲜度 = 当前时间 - 特征最近有效更新时间
新鲜度等级 时间间隔 处置动作
新鲜 < 1 小时 正常使用
较新鲜 1~6 小时 持续监控
陈旧 6~24 小时 降级使用
过期 > 24 小时 拦截并告警

3.6 特征覆盖率

特征覆盖率评估特征在目标群体中的有效覆盖比例,反映特征的实际可用性。覆盖率低意味着该特征对大部分样本无效,模型依赖该特征时会产生大量缺失。

特征覆盖率 = (有效值记录数 / 目标群体总记录数) × 100%

有效值定义为非缺失、非异常的值。覆盖率低于 60% 的特征应标记为"低覆盖",在模型训练和线上推理时需特殊处理。

3.7 指标关系与巡检流程

六大指标构成完整的特征缺失巡检链路,下图展示其协作关系:

特征缺失巡检指标协作流程 原始特征数据 缺失率 空值率 零值率 异常波动率 特征新鲜度 特征覆盖率 缺失巡检报告 + 拦截决策 第一层指标(绿)直接反映数据缺失状态;第二层指标(紫)评估特征时效性与可用性;最终输出(红)为巡检报告与拦截策略

3.8 指标计算示例

以下 Python 代码展示如何批量计算六大指标,适用于每日巡检任务:

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

def compute_missing_indicators(df, feature_col, time_col=None):
    """
    计算特征缺失六大指标
    :param df: DataFrame,包含特征列
    :param feature_col: 特征列名
    :param time_col: 时间列名(用于新鲜度计算)
    :return: dict,包含所有指标值
    """
    total = len(df)
    null_count = df[feature_col].isnull().sum()
    empty_count = (df[feature_col].astype(str).str.strip() == '').sum()
    placeholder_count = (df[feature_col].isin(['-999', 'N/A', 'Unknown'])).sum()
    
    # 缺失率 = NULL + 空字符串 + 占位符
    missing_rate = (null_count + empty_count + placeholder_count) / total
    
    # 空值率 = 仅 NULL
    null_rate = null_count / total
    
    # 零值率
    zero_rate = (df[feature_col] == 0).sum() / total
    
    # 异常波动率(需历史数据,此处简化)
    # 假设历史均值为 hist_mean
    hist_mean = 0.15  # 示例值
    current_mean = df[feature_col].mean()
    anomaly_volatility = abs(current_mean - hist_mean) / hist_mean if hist_mean != 0 else 0
    
    # 特征新鲜度
    freshness = None
    if time_col is not None:
        latest_time = df[time_col].max()
        freshness = (datetime.now() - latest_time).total_seconds() / 3600  # 小时
    
    # 特征覆盖率
    valid_count = total - null_count - empty_count - placeholder_count
    coverage = valid_count / total
    
    return {
        'feature': feature_col,
        'missing_rate': round(missing_rate, 4),
        'null_rate': round(null_rate, 4),
        'zero_rate': round(zero_rate, 4),
        'anomaly_volatility': round(anomaly_volatility, 4),
        'freshness_hours': round(freshness, 2) if freshness else None,
        'coverage': round(coverage, 4)
    }

# 使用示例
sample_df = pd.DataFrame({
    'income': [5000, None, 0, 8000, '', 6000, -999, 7000, None, 9000],
    'event_time': pd.date_range(end=datetime.now(), periods=10, freq='H')
})
result = compute_missing_indicators(sample_df, 'income', 'event_time')
print(result)
输出示例:{'feature': 'income', 'missing_rate': 0.4, 'null_rate': 0.2, 'zero_rate': 0.1, 'anomaly_volatility': 0.32, 'freshness_hours': 0.0, 'coverage': 0.6}

3.9 指标阈值速查

下表汇总各指标的推荐阈值与处置建议,供巡检系统配置参考:

指标 正常范围 预警阈值 拦截阈值 处置动作
缺失率 < 3% 3%~10% > 10% 降级/拦截
空值率 < 2% 2%~5% > 5% 告警排查
零值率 依业务定 突增 > 15% 突增 > 30% 拦截
异常波动率 < 20% 20%~50% > 50% 拦截并告警
特征新鲜度 < 1h 1h~6h > 6h 降级/拦截
特征覆盖率 > 80% 60%~80% < 60% 标记低覆盖
最佳实践:阈值需根据业务场景动态调整。例如,在贷前审批场景,缺失率容忍度较低(< 5%);在贷后监控场景,可适当放宽至 10%。建议每季度复盘阈值合理性。