Pandas:独热编码中将NaN与未见过类别视为未知值的实现方法
解决独热编码中测试集未知类别与NaN的统一处理问题
嘿,这个问题我之前做分类模型的时候也碰到过——既要处理测试集里没见过的新类别,又得把NaN也当成「未知类别」来统一编码成全0,对吧?其实有两种很实用的解决思路,咱们一步步来拆解。
核心需求回顾
训练集用pd.get_dummies生成了固定列的独热编码,测试集里可能出现两种「异常值」:
- 训练集从未出现的新类别(比如
Mercedes) - 缺失值
NaN
我们需要把这两种情况都处理成对应训练集编码列全为0的结果。
方法一:简洁版——编码+重索引+填充0
这是最直接的实现方式,利用reindex对齐列后填充NaN为0,一步到位:
import pandas as pd import numpy as np # 1. 训练集编码(原流程不变) train = pd.DataFrame({'car': ['Audi', 'BMW', 'Mazda']}) train_encoded = pd.get_dummies(train, columns=['car']) # 2. 测试集示例:包含新类别、NaN、已知类别 test = pd.DataFrame({'car': ['Mercedes', pd.NA, 'Audi']}) # 3. 处理测试集:编码→对齐训练集列→填充NaN为0 test_encoded_final = ( pd.get_dummies(test, columns=['car']) .reindex(columns=train_encoded.columns) .fillna(0) .astype(int) ) print(test_encoded_final)
输出结果:
car_Audi car_BMW car_Mazda 0 0 0 0 # Mercedes(新类别)→ 全0 1 0 0 0 # NaN → 全0 2 1 0 0 # Audi(已知类别)→ 正常编码
为什么这能生效?
- 新类别:
pd.get_dummies会为它生成专属列,但reindex会只保留训练集的列,专属列被丢弃后,原有训练集列的值都是NaN,填充0就得到全0。 - NaN:默认
pd.get_dummies不会为NaN生成列,所以编码后的测试集没有任何car_*列,reindex后所有训练集列都是NaN,填充0后也得到全0。
方法二:直观版——先标记未知值再编码
如果需要更清晰的调试和可控性,可以先把所有「未知值」(新类别+NaN)统一标记为一个训练集不存在的占位符,再编码对齐:
import pandas as pd import numpy as np # 1. 训练集编码(原流程不变) train = pd.DataFrame({'car': ['Audi', 'BMW', 'Mazda']}) train_encoded = pd.get_dummies(train, columns=['car']) # 2. 提取训练集的所有已知类别 train_categories = set(train['car'].unique()) # 3. 测试集预处理:把不在训练集的类别/NaN替换为「Unknown」 test = pd.DataFrame({'car': ['Mercedes', pd.NA, 'Audi']}) test['car'] = test['car'].apply(lambda x: x if x in train_categories else 'Unknown') # 4. 编码并对齐列 test_encoded_final = ( pd.get_dummies(test, columns=['car']) .reindex(columns=train_encoded.columns) .fillna(0) .astype(int) ) print(test_encoded_final)
优势:
- 处理逻辑更透明,你可以随时查看哪些值被标记为了未知,方便调试。
- 如果后续需要对未知类别做特殊处理(比如单独保留一个
car_Unknown列),只需要调整reindex的逻辑即可。
内容的提问来源于stack exchange,提问作者anon_swe
相关产品推荐
相关产品推荐

