含缺失值的有序/无序分类与数值数据的OneHot编解码及KNN填充
处理含有序/无序分类列的DataFrame缺失值填充与编码还原
问题分析
原始代码存在以下核心问题:
- 未区分有序分类列与无序分类列的编码逻辑:有序分类(如
category_with_order的a<b<c<d层级关系)应使用序数编码,而非独热编码;仅无序分类(如category_without_order)适合独热编码 - 直接对含缺失值的分类列做独热编码会生成异常的
nan列 - 数值列
sugar、salt被存储为字符串类型,无法直接用于KNN填充计算 - 错误拼接原数据与编码后数据,未正确构建用于填充的特征矩阵
修正后的完整代码
import pandas as pd import numpy as np from sklearn.preprocessing import OrdinalEncoder, OneHotEncoder from sklearn.impute import KNNImputer # 1. 初始化数据并预处理数值列 data = { 'category_with_order': ['a', 'b', 'c','d',np.nan], 'category_without_order': ['plant',np.nan,'salad','meat', 'drinks'], 'sugar': ['1',np.nan, '2', '2',np.nan], 'salt': ['1',np.nan, '2', '1',np.nan] } df = pd.DataFrame(data) # 将字符串类型的数值列转为浮点型 df[['sugar', 'salt']] = df[['sugar', 'salt']].astype(float) # 2. 区分有序/无序分类列进行编码 # 有序分类列编码:指定类别顺序,保留缺失值 ordinal_encoder = OrdinalEncoder(categories=[['a', 'b', 'c', 'd']], handle_unknown='use_encoded_value', unknown_value=np.nan) encoded_ordinal = pd.DataFrame(ordinal_encoder.fit_transform(df[['category_with_order']]), columns=['category_with_order']) # 无序分类列编码:临时填充缺失值避免生成nan列 onehot_encoder = OneHotEncoder(sparse_output=False, handle_unknown='ignore') # 临时用占位符填充缺失值,编码后再处理 temp_onehot_input = df[['category_without_order']].fillna('temp_missing') encoded_onehot = pd.DataFrame(onehot_encoder.fit_transform(temp_onehot_input), columns=onehot_encoder.get_feature_names_out()) # 3. 构建完整特征矩阵 feature_matrix = pd.concat([encoded_ordinal, encoded_onehot, df[['sugar', 'salt']]], axis=1) # 4. KNN填充所有缺失值 knn_imputer = KNNImputer(n_neighbors=1) filled_matrix = knn_imputer.fit_transform(feature_matrix) filled_feature_df = pd.DataFrame(filled_matrix, columns=feature_matrix.columns) # 5. 解码还原原始分类列 # 还原有序分类列 filled_feature_df['category_with_order'] = ordinal_encoder.inverse_transform(filled_feature_df[['category_with_order']]) # 还原无序分类列:将独热编码转为原始类别 onehot_cols = onehot_encoder.get_feature_names_out() # 找到每一行概率最高的类别索引,映射回原始值 filled_onehot_indices = filled_feature_df[onehot_cols].idxmax(axis=1).str.replace('category_without_order_', '') filled_feature_df['category_without_order'] = filled_onehot_indices.replace('temp_missing', np.nan) # 还原临时占位符 # 6. 整理最终结果,匹配原始表头 final_df = filled_feature_df[df.columns] print("填充后的最终DataFrame:") print(final_df)
关键步骤说明
- 数值列预处理:将字符串类型的
sugar、salt转为浮点型,确保KNNImputer可基于数值距离计算填充值 - 分类编码区分:
- 有序分类列用
OrdinalEncoder指定类别顺序,保留缺失值标记,保证层级关系不丢失 - 无序分类列用
OneHotEncoder时,先临时填充缺失值避免生成异常nan列,后续再还原
- 有序分类列用
- 缺失值填充:基于编码后的完整特征矩阵做KNN填充,覆盖分类、数值列的所有缺失值
- 解码还原:通过编码器的
inverse_transform方法将编码特征转回原始分类值,最终得到与原始表头一致的填充后DataFrame
内容的提问来源于stack exchange,提问作者yoopiyo
相关产品推荐
相关产品推荐

