数据预处理就像烹饪前的食材处理环节——没人会把带着泥土的胡萝卜直接扔进锅里。我在金融风控和电商用户行为分析领域处理过上百个数据集,90%的模型效果差异都源于预处理阶段的细节处理。去年我们团队用同一套算法对比经过预处理和原始数据的效果,AUC指标相差高达0.3,这个差距足以让一个风控模型从"可用"变成"行业领先"。
真实世界的数据永远充满"惊喜":传感器采集的温度数据里突然出现"-999"的魔法值;用户年龄字段里既有"1985-03-12"的日期格式又有"三十五岁"的文本描述;电商评论里夹杂着"发货快!!!"和""的混合内容。这些"脏数据"会像砂糖里的盐粒一样,彻底破坏后续分析的"口感"。
缺失值处理远不止简单的均值填充。在医疗数据中,某指标的缺失本身可能就是重要特征——未检测HIV往往意味着低风险群体。我常用的处理策略包括:
异常值检测需要结合业务场景。信用卡交易中,单笔消费20万可能是欺诈也可能是奢侈品购买。我推荐使用改进的箱线图法:
python复制Q1 = df['amount'].quantile(0.25)
Q3 = df['amount'].quantile(0.75)
IQR = Q3 - Q1
upper_bound = Q3 + 3*IQR # 传统方法用1.5倍,这里放宽到3倍
日期特征的处理往往被低估。除了简单的年/月/日提取,这些技巧效果显著:
文本字段的预处理有黄金法则:
重要提示:永远在拆分训练集/测试集之后再做TF-IDF等统计特征提取,避免数据泄露
银行数据常见问题:
我们的解决方案:
python复制# 身份证号标准化
df['id_no'] = df['id_no'].str.upper().str.replace('[^0-9X]', '')
# 金额有效性检查
valid_amount = (df['amount'] > 0) &
(df['amount'] <= 1e7) &
(~df['amount'].astype(str).str.match('1234|6666'))
# 时间修复函数
def fix_timestamp(ts):
if ts > datetime.now():
return ts - timedelta(days=365*20) # 假设是2038年问题
return ts
用户点击流数据的挑战:
我们的处理流程:
regex复制(android|ios)_(\w+)=([^&]+)
图像数据的预处理要点:
音频数据的处理技巧:
使用sklearn-compose构建可复用的预处理管道:
python复制from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
preprocessor = ColumnTransformer(
transformers=[
('num', numeric_transformer, numeric_features),
('cat', categorical_transformer, categorical_features),
('txt', text_transformer, text_features)
])
full_pipeline = Pipeline(steps=[
('preprocessor', preprocessor),
('imputer', IterativeImputer()),
('scaler', RobustScaler())
])
处理大型数据集时:
python复制df['gender'] = df['gender'].astype('category')
时间序列的陷阱:
分类数据的坑:
数值型数据的误区:
预处理质量的评估体系:
数据一致性检查
统计分析验证
下游任务验证
我习惯用Great Expectations库建立数据质量契约:
python复制expectation_suite = ExpectationSuite("data_quality")
validator.expect_column_values_to_not_be_null("user_id")
validator.expect_column_values_to_be_between("age", 18, 100)
validator.expect_column_pair_values_A_to_be_greater_than_B(
"order_time", "payment_time"
)
预处理后的数据应该达到"三无"标准:
在实际项目中,我会保留所有预处理步骤的详细日志,包括: