数据预处理全流程(一个数据集贯穿),入门级包学包会
假设原始数据是一张用户表:
ID | 年龄 | 薪资 | 城市 | 购买次数 |
1 | 25 | 8000 | 北京 | 5 |
2 | 30 | ? | 上海 | 12 |
3 | 25 | 8000 | 北京 | 5 |
4 | 200 | 12000 | 深圳 | 3 |
5 | 35 | 15000 | ? | 8 |
6 | 28 | 10000 | 广州 | 0 |
① 缺失值处理
方法 | 怎么做 | 本例结果 |
删除 | 直接去掉该行 | 删掉 ID=2(缺薪资)、ID=5(缺城市) |
填充均值 | 用其他行的平均值填 | 薪资 → (8000+12000+10000)/3 =10000 |
填充众数 | 用出现最多的值填 | 城市 →北京(出现2次最多) |
填充固定值 | 统一填一个数 | 城市 →未知 |
实际最常用:数值型填均值,类别型填众数。
② 重复值处理
ID=1 和 ID=3 完全一样:
操作 | 结果 |
删除重复 | 留一行,删一行 |
保留最后出现 | 留 ID=3 |
python df.drop_duplicates() # 默认保留第一条③ 异常值处理
ID=4 年龄=200,明显是异常:
方法 | 怎么做 | 本例结果 |
删除 | 直接删 | 删掉 ID=4 |
截断(Capping) | 超过上限的全部设为上限 | 年龄 >100 的全改成100 |
视为缺失 | 当成缺失值,再用均值填 | 年龄=200 → 缺失 → 填均值 28 |
业务敏感数据(如年龄)用截断,不要直接删。
④ 编码(让机器能读懂文字)
城市是文字,模型看不懂,必须转数字:
方法 | 结果 | 适用场景 |
Label Encoding | 北京=0, 上海=1, 深圳=2, 广州=3 | 有大小关系的(如等级) |
One-Hot Encoding | 北京→[1,0,0,0],上海→[0,1,0,0]... | 无大小关系的(如城市) |
One-Hot 后的表:
年龄 | 薪资 | 北京 | 上海 | 深圳 | 广州 | 购买次数 |
25 | 8000 | 1 | 0 | 0 | 0 | 5 |
30 | 10000 | 0 | 1 | 0 | 0 | 12 |
... | ... | ... | ... | ... | ... | ... |
⑤ 标准化 / 归一化(让量纲一致)
年龄范围 20~100,薪资范围 5000~20000,数字差距太大,模型会被薪资主导。
方法 | 公式 | 结果范围 | 本例(年龄25) |
归一化 (Min-Max) |
| [0, 1] | (25-20)/(100-20) =0.0625 |
标准化 (Z-Score) |
| 均值0,标准差1 | (25-28)/4 ≈-0.75 |
选哪个? |
有明确上下界(如0~100分)→ 归一化 |
没有明确边界(如薪资)→ 标准化 |
树模型(随机森林、XGBoost)→不需要做 |
⑥ 二值化(刚才讲过)
购买次数 → 是否活跃:
原始 | 阈值≥5 | 结果 |
5 | ≥5 | 1(活跃) |
12 | ≥5 | 1 |
0 | <5 | 0(不活跃) |
⑦ 特征选择(少即是多)
方法 | 思路 |
删低方差列 | 所有人城市都一样 → 删掉 |
删高相关列 | 薪资和年收入几乎一样 → 留一个 |
业务判断 | ID 对预测没用 → 删掉 |
完整流程一览
原始数据 → ① 缺失值处理(填/删) → ② 重复值处理(删) → ③ 异常值处理(删/截断/填) → ④ 编码(文字→数字) → ⑤ 标准化/归一化(量纲统一) → ⑥ 二值化/分箱(按需) → ⑦ 特征选择(降维) → 干净数据 → 喂模型