get_dummies生成多维二值列,适用于类别少(≤10)、模型可接受稀疏输入的one-hot场景;factorize生成单维整数ID,适用于类别多、需控制维度爆炸或对接嵌入层/树模型的label-like编码场景。

别直接套用 get_dummies 或 factorize —— 它们解决的是两类完全不同的建模需求:一个是“拆成多维二值信号”,一个是“压缩成单维整数 ID”。
什么时候该用 get_dummies?
当你需要把类别变量转为互斥的二进制列(即 one-hot),且类别数不多(比如 ≤ 10)、模型能承受稀疏输入时,get_dummies 是最直接的选择。
- 默认只对
object或category类型列生效,数值列(如int64)不会被自动编码,除非你显式传入columns - 遇到缺失值会直接跳过,加
dummy_na=True才会额外生成一列colname_nan - 设
drop_first=True可去掉首列,避免线性回归中的共线性问题;但树模型(如RandomForest)不需要这步 - 返回的是新列拼接的
DataFrame,原列自动丢弃;若想保留原列,得先df.copy()再删
示例:pd.get_dummies(df, columns=['city'], prefix='city', drop_first=True) → 原 city 列消失,新增 city_beijing、city_shanghai 等(首城被删)
什么时候该用 factorize?
当你只想给每个唯一值分配一个稳定整数 ID(类似 label encoding),且后续要喂给需要连续数值输入的模型(如 LightGBM 的 categorical 参数、或嵌入层),或者你明确想控制维度爆炸风险时,factorize 更合适。
立即学习“Python免费学习笔记(深入)”;
- 它只返回两个值:
labels(编码后的一维数组)和uniques(原始唯一值的索引),常用写法是df['col_encoded'] = pd.factorize(df['col'])[0] -
na_sentinel=-1是默认行为,所有NaN都变成 -1;若想让NaN单独占一个 ID,得先fillna或手动处理 - 不支持
prefix、drop_first这类参数 —— 它压根不生成多列,谈不上“前缀”或“去首” - 编码顺序取决于首次出现顺序(
sort=False),不是字典序;若需固定顺序,得先sort=True或用Categorical显式定义
示例:df['country_id'] = pd.factorize(df['country'])[0] → country 列还在,新增一列 country_id,值为 0, 1, 2...
get_dummies 和 factorize 混用的典型陷阱
最常踩的坑是:在训练集上用 get_dummies 编码,测试集直接 get_dummies —— 若测试集出现了训练集没见过的新类别,就会导致列数不一致,fit 报错或预测出错。
-
factorize同样有这个问题:新值会被统一映射为na_sentinel(-1),但你得自己决定 -1 是当作未知类、还是过滤掉、还是补均值 - 真正稳健的做法是:用
sklearn.preprocessing.OneHotEncoder(handle_unknown='ignore')或CategoryEncoders库,它们支持fit/transform分离,并能处理未见类别 - 如果坚持用 pandas,至少得保存
uniques结果(pd.factorize的第二返回值)或列名列表(get_dummies后的columns),并在测试集上对齐
另一个隐形坑:get_dummies 默认对所有 object 列批量处理,容易误伤本应保留的 ID 类字符串(如用户 user_id);而 factorize 对单列操作更可控,但也更容易漏掉多列同步编码逻辑。
选哪个,关键看你的下游模型和数据规模
类别数少(LogisticRegression)、追求可解释性 → 优先 get_dummies;类别数大(>50)、内存敏感、准备接 embedding 或树模型 → factorize 更轻量。但两者都不是生产环境的终点:真实项目里,你几乎总会需要跨训练/测试集的一致映射能力,而这必须靠显式的 fit + transform 流程来保障。


















