封装的代码如下,文件名为my_one_hot_encoder.py
import pandas as pdfrom sklearn.preprocessing import OneHotEncoder, LabelEncoderclass One_hot_encoder: def __init__(self, df, column_name_list): self.df = df self.column_name_list = column_name_list def multi_column_encoder(self): Enc_ohe, Enc_label = OneHotEncoder(), LabelEncoder() for column_name in self.column_name_list: self.df["Dummies"] = Enc_label.fit_transform(self.df[column_name]) self.df_dummies = pd.DataFrame(Enc_ohe.fit_transform(self.df[["Dummies"]]).todense(), columns = Enc_label.classes_) self.df_dummies.rename(columns=lambda x: column_name + "_" + x, inplace=True) self.df = pd.concat([self.df, self.df_dummies], axis=1) self.df.drop(["Dummies"], axis=1, inplace=True) self.df.drop(self.column_name_list, axis=1, inplace=True) return self.df
测试转换数据代码如下,文件名称为test_one_hot_encoder.py
import pandas as pdfrom my_one_hot_encoder import One_hot_encoderif __name__ == '__main__': df = pd.read_excel("D:/data/testdata.xlsx") column_name_list = ["pet", "city"] df_encoded = One_hot_encoder(df, column_name_list).multi_column_encoder() print(df_encoded)
##testdata.xlsx数据明细如下:age city pet salary4 beijing cat 46 shenzhen dog 53 guangzhou dog 13 shenzhen fish 1
##执行python test_one_hot_encoder.py,结果如下所示:
age salary pet_cat pet_dog pet_fish city_beijing city_guangzhou \0 4 4 1.0 0.0 0.0 1.0 0.01 6 5 0.0 1.0 0.0 0.0 0.02 3 1 0.0 1.0 0.0 0.0 1.03 3 1 0.0 0.0 1.0 0.0 0.0 city_shenzhen0 0.01 1.02 0.03 1.0
##LabelEncoder() & OneHotEncoder() 与get_dummies的利与弊
1、get_dummies 不像 sklearn 的 transformer一样,有 transform方法,所以一旦测试集中出现了训练集未曾出现过的特征取值,简单地对测试集、训练集都用 get_dummies 方法将导致数据错误。
2、不是 sklearn 里的transformer类型,所以得到的结果得手动输入到 sklearn 里的相应模块,也无法像 sklearn 的transformer一样可以输入到pipeline中 进行流程化地机器学习过程。
3、使用LabelEncoder() & OneHotEncoder()重新封装的方法,可以完美解决LabelEncoder不接受多列输入的问题,也解决了,在使用get_dummies时测试集中出现训练集未曾出现过的特征取值会报错的问题;当然重新封装的方法也可以进一步改成pipeline模式操作。