如何对指定特征执行目标引导编码(Target Encoder)并排除nan值,解决KeyError报错
错误原因
- 循环逻辑错误:
for i in df['gender']遍历的是gender列的实际值(如'Male'),后续df[i]尝试访问名为'Male'的列,数据集无该列直接触发KeyError - 编码器调用错误:TargetEncoder的fit_transform方法要求传入二维特征结构,直接传入一维Series会触发格式错误,且不需要放在循环中重复调用
- 空值判断风险:若数据集中的nan是真实缺失值(非字符串'nan'),
!= 'nan'的判断逻辑完全失效
正确实现方案(基于category_encoders库)
核心逻辑是拆分空值与非空值,仅对非空值执行编码,空值直接保留:
import pandas as pd import numpy as np from category_encoders import TargetEncoder encoder = TargetEncoder() # 非空值掩码,若你的空值是字符串'nan',将pd.isna替换为lambda x: x == 'nan'即可 non_na_mask = ~pd.isna(df['gender']) # 仅对非空值拟合编码,注意传入二维结构(加[[]]) df.loc[non_na_mask, 'gender'] = encoder.fit_transform( df.loc[non_na_mask, ['gender']], df.loc[non_na_mask, 'target'] )
注意:目标编码存在标签泄露风险,拟合编码器时请仅使用训练集数据,禁止引入测试集数据参与拟合,否则会导致模型评估结果失真。
其他可行实现方案
- 手动计算目标编码(无第三方库依赖)
直接通过分组统计目标均值实现编码,逻辑透明可控:
# 统计非空gender分类对应的target均值 target_mean_map = df[~pd.isna(df['gender'])].groupby('gender')['target'].mean().to_dict() # 映射编码,空值直接保留 df['gender'] = df['gender'].map(target_mean_map).fillna(df['gender'])
- Pipeline封装实现(适配机器学习流水线场景)
将编码逻辑封装为可接入sklearn pipeline的组件,适合工程化落地:
from sklearn.preprocessing import FunctionTransformer from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline def custom_target_encode(X, y=None): X = X.copy() col = X.columns[0] non_na_mask = ~pd.isna(X[col]) if y is not None: mean_map = y[non_na_mask].groupby(X.loc[non_na_mask, col]).mean().to_dict() X.loc[non_na_mask, col] = X.loc[non_na_mask, col].map(mean_map) return X gender_encoder = Pipeline(steps=[ ('target_enc', FunctionTransformer(custom_target_encode)) ]) preprocessor = ColumnTransformer( transformers=[('gender_enc', gender_encoder, ['gender'])], remainder='passthrough' ) # 拟合转换全流程 processed_df = preprocessor.fit_transform(df, df['target'])
内容的提问来源于stack exchange,提问作者User1011
相关产品推荐
相关产品推荐

