2. 原始数据探索:数据类型识别与缺失异常分析

在模型训练流程中,原始数据探索是变量衍生与分箱的前置基础。本章聚焦于两个核心任务:数据类型识别(数值型、类别型、文本型、时间型)与缺失值/异常值初步分析。准确的数据类型判断决定了后续特征工程的策略选择,而缺失与异常分析则直接影响数据清洗与变量质量。

2.1 数据类型识别:四类基础形态

原始数据通常以表格形式存储,每一列对应一个变量。根据存储内容与语义,可将数据类型划分为以下四类:

数据类型 典型特征 常见示例 后续处理方向
数值型 可进行算术运算,有大小顺序 年龄、收入、温度、交易金额 标准化、分箱、多项式衍生
类别型 有限离散取值,无大小意义 性别、城市、产品类别、颜色 独热编码、标签编码、频次编码
文本型 自由文本,长度不固定 评论、描述、地址、日志 TF-IDF、词嵌入、长度统计
时间型 日期或时间戳,可提取周期特征 注册日期、交易时间、生日 时间差、星期/月份/季度提取
实践提示: 在Python中,使用 df.dtypes 可快速查看各列数据类型。但需注意:object 类型可能同时代表类别型或文本型,需结合唯一值数量(nunique())进一步判断。若唯一值数量较少(如 < 20),通常视为类别型;若唯一值数量接近样本量,则多为文本型。

2.2 数据类型识别流程

以下流程图展示了从原始数据到类型标注的标准化判断路径:

数据类型识别判断流程 原始数据列 是否为数值类型? 是 数值型 否 是否为时间类型? 时间型 否 唯一值数量 < 阈值? (通常阈值=20) 是 类别型 否 文本型 阈值可根据业务场景调整:类别型通常 < 20 个唯一值,文本型往往 > 100 甚至接近样本量 时间型需通过正则或日期解析库(如 pandas.to_datetime)辅助识别
关键判断规则:
  • 数值型:dtype 为 int64 或 float64,且值域连续。
  • 类别型:dtype 为 object 或 category,唯一值数量 ≤ 20。
  • 文本型:dtype 为 object,唯一值数量 > 20 且字符串平均长度较长。
  • 时间型:dtype 为 datetime64,或可通过 pd.to_datetime() 成功转换。

2.3 缺失值初步分析

缺失值分析是数据质量评估的第一步。需要从缺失比例、缺失模式、缺失与目标变量的关系三个维度展开。

2.3.1 缺失比例统计

使用以下代码快速计算各列的缺失比例:

import pandas as pd

# 计算缺失比例
def missing_analysis(df):
    missing_count = df.isnull().sum()
    missing_pct = (missing_count / len(df)) * 100
    result = pd.DataFrame({
        '缺失数量': missing_count,
        '缺失比例(%)': missing_pct.round(2)
    })
    result = result[result['缺失数量'] > 0].sort_values('缺失比例(%)', ascending=False)
    return result

# 示例调用
missing_df = missing_analysis(data)
print(missing_df.head(10))
缺失比例区间 处理建议 风险等级
< 1% 直接删除缺失行或均值/中位数填充 低
1% - 5% 根据变量重要性选择填充策略(均值/中位数/众数) 中
5% - 20% 需分析缺失模式,考虑模型预测填充或单独编码 高
> 20% 建议删除该变量,或构造“是否缺失”指示变量 极高

2.3.2 缺失模式可视化

缺失模式可分为三种类型:

  • 完全随机缺失(MCAR):缺失与任何变量无关,可直接删除或简单填充。
  • 随机缺失(MAR):缺失与其他观测变量相关,需使用多重插补或模型预测。
  • 非随机缺失(MNAR):缺失与缺失值本身相关,处理最为复杂,需引入外部信息。
注意: 在金融风控、医疗诊断等场景中,缺失值本身可能包含信息。例如,用户未填写收入字段可能暗示收入不稳定。此时建议将“是否缺失”作为独立特征加入模型。

2.4 异常值初步分析

异常值是指明显偏离正常分布的数据点。初步分析阶段主要采用统计阈值法和箱线图法进行快速筛查。

2.4.1 常用异常值检测方法

方法 适用场景 判定规则 优缺点
Z-Score 法 近似正态分布 |Z| > 3 视为异常 简单快速,但对偏态分布不鲁棒
IQR 四分位距法 任意分布 超出 Q1-1.5IQR 或 Q3+1.5IQR 不受极端值影响,适合偏态数据
MAD 中位数绝对偏差法 含较多异常值 |x - median| > 3 * MAD 比 Z-Score 更稳健
DBSCAN 聚类法 高维或复杂分布 未被归入任何簇的点 可发现非球形异常,但参数敏感

2.4.2 异常值处理策略

初步分析阶段不急于处理异常值,而是先记录异常点的数量、比例和分布特征。后续章节将在分箱与变量衍生中结合业务逻辑进行针对性处理。

# IQR 法检测异常值示例
def detect_outliers_iqr(series):
    Q1 = series.quantile(0.25)
    Q3 = series.quantile(0.75)
    IQR = Q3 - Q1
    lower_bound = Q1 - 1.5 * IQR
    upper_bound = Q3 + 1.5 * IQR
    outliers = series[(series < lower_bound) | (series > upper_bound)]
    return outliers, lower_bound, upper_bound

# 示例:检测 'age' 列的异常值
outliers, lb, ub = detect_outliers_iqr(data['age'])
print(f"异常值数量: {len(outliers)}")
print(f"正常范围: [{lb:.2f}, {ub:.2f}]")
初步分析输出清单:
  1. 每列的数据类型标注(数值/类别/文本/时间)
  2. 缺失值比例排名(前 10 列)
  3. 缺失模式判断(MCAR/MAR/MNAR)
  4. 异常值数量与比例(每列)
  5. 异常值分布区间(最小值、最大值、异常边界)

2.5 综合示例:数据类型与缺失异常联合分析

以下代码整合了本节的核心分析流程,适用于原始数据探索阶段:

def data_exploration_summary(df):
    summary = pd.DataFrame(index=df.columns)
    summary['数据类型'] = df.dtypes.astype(str)
    summary['唯一值数量'] = df.nunique().values
    summary['缺失数量'] = df.isnull().sum().values
    summary['缺失比例(%)'] = (summary['缺失数量'] / len(df) * 100).round(2)
    
    # 数值列异常值统计
    num_cols = df.select_dtypes(include=['int64', 'float64']).columns
    outlier_counts = []
    for col in num_cols:
        Q1 = df[col].quantile(0.25)
        Q3 = df[col].quantile(0.75)
        IQR = Q3 - Q1
        lower = Q1 - 1.5 * IQR
        upper = Q3 + 1.5 * IQR
        count = ((df[col] < lower) | (df[col] > upper)).sum()
        outlier_counts.append(count)
    summary.loc[num_cols, '异常值数量'] = outlier_counts
    summary = summary.fillna('-')
    return summary

# 输出探索摘要
explore_result = data_exploration_summary(data)
print(explore_result.head(15))

通过上述分析,可快速定位数据中的质量问题,为后续的变量衍生与分箱提供清晰的输入。下一阶段将基于这些分析结果,针对不同数据类型设计差异化的特征工程策略。