2. 原始数据探索:数据类型识别与缺失异常分析
在模型训练流程中,原始数据探索是变量衍生与分箱的前置基础。本章聚焦于两个核心任务:数据类型识别(数值型、类别型、文本型、时间型)与缺失值/异常值初步分析。准确的数据类型判断决定了后续特征工程的策略选择,而缺失与异常分析则直接影响数据清洗与变量质量。
2.1 数据类型识别:四类基础形态
原始数据通常以表格形式存储,每一列对应一个变量。根据存储内容与语义,可将数据类型划分为以下四类:
| 数据类型 | 典型特征 | 常见示例 | 后续处理方向 |
|---|---|---|---|
| 数值型 | 可进行算术运算,有大小顺序 | 年龄、收入、温度、交易金额 | 标准化、分箱、多项式衍生 |
| 类别型 | 有限离散取值,无大小意义 | 性别、城市、产品类别、颜色 | 独热编码、标签编码、频次编码 |
| 文本型 | 自由文本,长度不固定 | 评论、描述、地址、日志 | TF-IDF、词嵌入、长度统计 |
| 时间型 | 日期或时间戳,可提取周期特征 | 注册日期、交易时间、生日 | 时间差、星期/月份/季度提取 |
实践提示: 在Python中,使用
df.dtypes 可快速查看各列数据类型。但需注意:object 类型可能同时代表类别型或文本型,需结合唯一值数量(nunique())进一步判断。若唯一值数量较少(如 < 20),通常视为类别型;若唯一值数量接近样本量,则多为文本型。
2.2 数据类型识别流程
以下流程图展示了从原始数据到类型标注的标准化判断路径:
关键判断规则:
- 数值型:
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}]")
初步分析输出清单:
- 每列的数据类型标注(数值/类别/文本/时间)
- 缺失值比例排名(前 10 列)
- 缺失模式判断(MCAR/MAR/MNAR)
- 异常值数量与比例(每列)
- 异常值分布区间(最小值、最大值、异常边界)
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))
通过上述分析,可快速定位数据中的质量问题,为后续的变量衍生与分箱提供清晰的输入。下一阶段将基于这些分析结果,针对不同数据类型设计差异化的特征工程策略。