两年前我接了一个收入预测的数据挖掘项目,数据集大概六万条、二十来个字段。第一次用决策树跑出来的准确率只有76%,调了半天超参也没明显起色。后来回头看才发现,问题根本不在模型,而在一整个特征工程环节——日期字段还是字符串,教育程度是文本分类,年龄和收入没有做任何交叉,缺失值直接用0填平,整套特征就像没洗没切的菜直接扔进锅里炒。也是从那个项目开始,我把Python大数据特征工程这条链路彻底理了一遍,Pandas负责把生数据洗成可用的特征集,Sklearn负责做特征选择、降维和建模验证。这个组合到今天仍然是我在绝大多数表格型大数据项目里的首选方案。
这篇文章就围绕这条链路来写,从数据清洗、特征构造、特征选择到Pipeline整合,最后用一个收入预测的完整案例把全流程串起来。无论你是刚开始转数据挖掘的新人,还是已经在业务里被脏数据折磨过好几轮的开发,都应该能从这里拿到一些可以直接抄走的方案。
1. 特征工程在大数据场景下的定位:Pandas和Sklearn各自的战场
很多人一上来就抱着模型手册啃,觉得XGBoost、LightGBM调参才是核心。实际做过几个项目就会明白,模型的上限是由数据决定的,特征工程才是决定你能多接近这个上限的那双手。Kaggle上有句流传很广的话:数据和特征工程决定了模型的上限,模型算法只是在逼近这个上限。放在大数据场景里,这句话更成立——数据量大、维度杂、质量参差不齐,特征工程投入的时间往往占整个建模流程的六成以上。
1.1 为什么单独聊特征工程
先泼一盆冷水:在真实业务里,90%的时间不是在调模型,而是在处理"怎么把几百个字段变成模型吃得下的东西"。原始数据通常长这样:
- 日期字段是"2024-05-11 14:32:08"这种字符串,模型不知道这是星期几、是不是周末、距离月末还有几天;
- 分类字段有几十个取值,有些取值明明含义相近却被拆成两列;
- 数值字段存在明显长尾,比如收入从3千到300万,直接喂给线性模型会被极端值带偏;
- 缺失值、重复值、脏数据混在一起,没人告诉你哪些字段该删、该填、该拆。
这些都是特征工程的活。说直白点,特征工程就是把人对业务的理解翻译成模型能听懂的数值语言。同样的数据,有人喂进去模型AUC只有0.72,有人能做到0.85,差的不是模型,而是翻译的质量。
1.2 Pandas和Sklearn在链路里的分工边界
工具选型这事,用顺手的就好,但职责必须分清。我的习惯很简单:Pandas管数据,Sklearn管特征加工和建模。
Pandas负责的部分包括数据的读写、探查、清洗、聚合,以及各种自定义规则的变换,因为它足够灵活,DataFrame一拿过来就能写脚本折腾。Sklearn负责的是标准化、编码、分箱、特征选择、降维这些已经有成熟算法实现的环节,因为它提供了统一的fit/transform接口,能直接嵌进Pipeline里,避免在训练集和测试集上重复写一套变换逻辑。
| 环节 | 主力工具 | 主要API |
|---|---|---|
| 数据读写与探查 | Pandas | read_csv, read_excel, info, describe |
| 数据清洗与转换 | Pandas | drop, fillna, astype, to_datetime |
| 缺失值填充/标准化 | Sklearn | SimpleImputer, StandardScaler |
| 类别编码 | Sklearn | OneHotEncoder, LabelEncoder |
| 分箱与离散化 | Pandas为主,Sklearn辅助 | pd.cut, pd.qcut, KBinsDiscretizer |
| 特征选择 | Sklearn | VarianceThreshold, SelectFromModel, RFECV |
| 降维 | Sklearn | PCA |
| 流程统一管理 | Sklearn | Pipeline, ColumnTransformer |
这里要单独提醒一点:Sklearn的接口非常严格,吃进去的必须是二维数值数组,字符串类别必须预先编码。所以Pandas在前面做清洗转格式、Sklearn在后面做数学变换,这个先后顺序本身也是一种约定。按这个分工往下走,每一步的输入输出都很清晰,出了bug也能很快定位是清洗的锅还是变换的锅。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据清洗实战:从脏数据到合格特征集
我在多个项目里反复踩过的坑之一,就是拿到数据就开始建模,连最基本的dtype和缺失率都没看。想走捷径的第一步,往往就是后面返工的开始。
2.1 数据加载与快速探查:read_excel和read_csv到底怎么用才高效
先说加载。Pandas读取excel和csv是几乎每天都会用到的基础操作,但很多人只用了最朴素的写法,大数据量场景下很容易吃内存亏。
python复制import pandas as pd
# 读取Excel,只选需要的sheet和列,大数据量时避免整表载入
df = pd.read_excel(
"data.xlsx",
sheet_name="train",
usecols=["age", "income", "education", "occupation", "apply_date"],
dtype={"cust_no": "string"}
)
# 读取CSV,大数据量时建议显式指定dtype和解析日期列
df = pd.read_csv(
"train.csv",
sep=",",
encoding="utf-8",
dtype={"duration": "int32", "amount": "float32"},
parse_dates=["apply_date"],
nrows=10000 # 第一次探查建议先只读一万行
)
很多人不知道dtype参数的作用。Pandas默认会用int64或float64去装数值列,但如果你的字段本来取值范围很小,指定成int32甚至int16,内存直接砍掉一半以上。parse_dates的作用是把日期字符串一次性解析成datetime类型,比读进来以后再to_datetime转一遍要省事得多。第一次看一份陌生数据,先用nrows读个一万行做探查,确认格式没问题再全量读入,这个习惯能帮你避开很多坑。
数据加载进来以后,不要急着敲模型。花两分钟做一次系统性探查:
python复制# 字段类型、非空数量、内存占用
df.info()
# 数值字段分布
df.describe().T
# 缺失率统计
missing_rate = df.isna().mean().sort_values(ascending=False)
# 唯一值数量,尤其关注分类字段
unique_counts = df.nunique()
info()会直接告诉你每个字段的dtype、非空个数和整体内存占用。nunique()是发现字段放错位置的好帮手——比如一个叫"customer_id"的列只有三个唯一值,那它多半不是ID,而是一个分类特征,甚至可以硬编码成三个级别。
2.2 类型转换:object、category、datetime换错了比缺数据还麻烦
Pandas数据类型转换是特征工程里最容易被忽略但又极其影响后续建模的环节。字符串类型"123"和数值类型123,在Sklearn里是两个完全不同的物种,模型根本不认识前者。
常见的转换场景有这么几类:
python复制# 数字列被误读成字符串:常见于金额列带了逗号或货币符号
df["amount"] = pd.to_numeric(df["amount"].str.replace(",", "").str.replace("¥", "")
