pd.get_dummies()是最直接的选择,因其是pandas原生函数,无需scikit-learn依赖,能自动处理nan(默认生成col_nan列)、保留列名前缀、跳过数值列,并返回可拼接的dataframe;但不保存编码状态,跨训练/测试集易因类别缺失导致列数不一致。

为什么 pd.get_dummies() 是最直接的选择
因为 Pandas 原生支持分类变量的快速 One-Hot 展开,无需额外依赖 scikit-learn,且能自动处理缺失值和列名冲突。它适合探索性分析、特征预处理初稿或轻量级 pipeline。
常见错误是直接对含 NaN 的列调用,结果会生成一列 col_nan —— 这不是 bug,而是默认行为;若不希望保留缺失指示列,得显式设 drop_first=False 并配合 dummy_na=False。
-
pd.get_dummies(df, columns=['cat_col'], dummy_na=False):禁用缺失值单独成列 - 若列已是
category类型(如用df['cat_col'] = df['cat_col'].astype('category')转换过),get_dummies会跳过未出现的类别,不会补全所有可能取值 - 多个列同时编码时,列名默认用下划线拼接(如
color_red),避免空格或特殊字符导致后续报错
如何让 One-Hot 编码结果与 scikit-learn 的 OneHotEncoder 对齐
当模型训练用 sklearn,但数据清洗在 Pandas 里做,就容易出现训练/预测阶段列数不一致的问题——比如测试集某分类变量值在训练集没出现过,pd.get_dummies() 直接忽略,而 OneHotEncoder(handle_unknown='ignore') 会保留对应列(全为 0)。
解决办法是统一用 sklearn.preprocessing.OneHotEncoder(sparse_output=False, drop='first', handle_unknown='ignore'),并配合 ColumnTransformer 只对指定列生效:
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer
ohe = OneHotEncoder(drop='first', handle_unknown='ignore')
preprocessor = ColumnTransformer(
transformers=[('cat', ohe, ['gender', 'city'])],
remainder='passthrough'
)
X_transformed = preprocessor.fit_transform(df)
注意:fit_transform() 返回的是 numpy.ndarray,列名丢失;如需 DataFrame,得手动重建列名,或改用 sklearn-pandas 等封装库。
遇到高基数分类变量(如 user_id)怎么办
直接 One-Hot 会导致维度爆炸,内存溢出或模型变慢。这不是编码方法错了,而是该换策略了。
- 先检查唯一值数量:
df['user_id'].nunique(),若 > 1000,基本别用 One-Hot - 可降维替代方案:
df.groupby('user_id')['target'].transform('mean')做目标编码,或用hashing trick(sklearn.feature_extraction.FeatureHasher)强制映射到固定维度 - 如果非要用 One-Hot 且确定稀疏性高,加参数
sparse=True到pd.get_dummies(),返回SparseDataFrame(Pandas 1.4+ 已弃用,建议转用scipy.sparse矩阵)
为什么 pd.get_dummies() 不支持“保存编码器状态”
因为它没有 fit / transform 分离机制——每次调用都是独立计算。这意味着:训练集用 get_dummies() 编码后得到 12 列,测试集若某个类别没出现,就只产出 11 列,直接喂给模型会报 ValueError: X has 11 features, but OneHotEncoder is expecting 12 features。
所以线上服务或跨批次处理时,必须用可序列化的编码器:
- 用
joblib.dump(ohe, 'ohe.pkl')保存已fit的OneHotEncoder - 测试阶段用
joblib.load('ohe.pkl').transform(test_df[['cat_col']]) - 若坚持用 Pandas,就得手动记录训练集所有唯一值:
train_cats = set(df_train['cat_col'].dropna()),再对测试集补全缺失列并置 0
这个差异点经常被忽略,直到部署时报错才意识到——Pandas 的便利性只在单次分析中成立。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











