pd.get_dummies()列名带奇怪后缀因默认对非数值列编码且空值/重复类别触发自动加序号;遇NaN默认生成city_nan列,应先fillna或设dummy_na=True;训练测试集须合并后统一编码以防列数不一致;高基数变量易致性能骤降,需先查nunique()再选top-k或目标编码。

为什么 pd.get_dummies() 生成的列名有时带奇怪后缀?
因为默认对所有非数值列都做独热编码,且当某列含空值或重复类别时,pd.get_dummies() 会自动在列名后加下划线和序号(比如 color_blue、color_red),但若原始列名本身含下划线或特殊字符,就容易混成 category_type_A 这种难读的形式。
实操建议:
- 用
prefix参数统一加前缀,比如prefix='cat',避免依赖默认命名 - 加
prefix_sep='_'显式声明分隔符,防止和原列名里的符号冲突 - 提前用
df[col].astype('category')规范类型,能减少空值引发的意外列分裂
pd.get_dummies() 遇到 NaN 怎么办?
默认会把 NaN 当作一个独立类别生成一列(如 city_nan),这通常不是你想要的——多数模型不能直接吃含 NaN 的独热列,反而引入噪声。
实操建议:
- 加参数
drop_first=False没用,关键在dummy_na=False(默认就是False,但显式写上更安心) - 真正有效的是先处理缺失:用
df['col'].fillna('MISSING')再编码,或直接删掉含 NaN 的行(df.dropna(subset=['col'])) - 如果必须保留 NaN 语义,就设
dummy_na=True,但后续得手动删掉那一列,否则训练时容易报错
训练集和测试集用 get_dummies() 要分开还是合并?
必须先合并再编码,否则训练集有的类别、测试集没有,会导致列数不一致,模型直接报 ValueError: X has 5 features per sample; expecting 6。
实操建议:
- 别对 train/test 分别调用
pd.get_dummies()—— 这是最常见翻车点 - 正确做法:用
pd.concat([train, test], keys=['train', 'test'])拼一起编码,再按 key 拆开 - 或者更稳妥:用
sklearn.preprocessing.OneHotEncoder(handle_unknown='ignore'),它能记住训练时见过的类别,测试时遇新值自动忽略 - 注意拼接后要重置索引,否则
get_dummies()可能因索引重复出错
性能差?10万行数据卡住?
pd.get_dummies() 在高基数分类变量(比如用户 ID、URL 字段)上会爆炸式生成几千列,内存飙升、速度骤降,甚至触发 MemoryError。
实操建议:
- 先用
df['col'].nunique()查基数,超过 100 就别硬上get_dummies() - 高频值只留 top-k,其余归为
other:用df['col'].value_counts().nlargest(10).index - 对超高基数字段,改用目标编码(Target Encoding)或哈希编码(
sklearn.feature_extraction.FeatureHasher) - 别忘了删原始列:
drop=True是默认行为,但显式写上更保险
类别多、分布偏、有缺失——这几个条件凑齐时,get_dummies() 很快就从便利工具变成隐患源头。动手前花三十秒看一眼 nunique() 和 isna().sum(),比后面 debug 两小时强得多。










