长表转宽表稀疏矩阵后,OneHotEncoder编码如何保留原始分类标签列名?
问题
将分类列编码为数字并将长表(LONG)转换为宽表(WIDE)得到稀疏矩阵后,希望检索列名对应的分类标签,以便在后续步骤中进行模型解释。
当前解决方案
以下是目前的解决方案,但流程十分繁琐,希望得到更优方法:
import pandas as pd from scipy.sparse import csr_matrix from sklearn.preprocessing import OneHotEncoder # Example dataframe data = { 'id':[13,13,14,14,14,15], 'name':['alex', 'mary', 'alex', 'barry', 'john', 'john'], 'categ': ['dog', 'cat', 'dog', 'ant', 'fox', 'seal'], 'size': ['big', 'small', 'big', 'tiny', 'medium', 'big'] } df = pd.DataFrame(data) # Create dictionaries from original dataframe to save categories # Part of the convoluted solution dcts = [] df_cols = ['categ', 'size'] for col in df_cols: cats = df[col].astype('category') dct = dict(enumerate(cats.cat.categories)) dcts.append(dct) # Change into category codes, otherwise sparse matrix cannot be built for col in ['categ', 'size']: df[col] = df[col].astype('category').cat.codes # Group by into sparse columns piv = df.groupby(['id', 'name'])[['categ', 'size']].first().astype('Sparse[int]') # Unstack keeps sparse format piv = piv.unstack(fill_value=0) piv.columns = piv.columns.to_flat_index().str.join('_') # Encoding gives poor column names encoder = OneHotEncoder(sparse_output=True) piv_enc = encoder.fit_transform(piv) piv_fin = pd.DataFrame.sparse.from_spmatrix( piv_enc, columns=encoder.get_feature_names_out())
当前生成的列名类似:'categ_alex_-', 'categ_alex_2.0', 'categ_barry_-', 'categ_barry_0.0',但需要保留原始分类标签,即列名应为'categ_alex_-', 'categ_alex_dog', 'categ_barry_-', 'categ_barry_ant'。
待优化的繁琐步骤
# Fixing column names piv_cols = list(piv_fin.columns) for (dct, df_col) in zip(dcts, df_cols): print(df_col, dct) for i, piv_col in enumerate(piv_cols): if df_col in piv_col: if piv_col[-1:] != '-': piv_cols[i] = piv_col[:-2] + '_' + dct[int(piv_col[-1:])] piv_fin.columns = piv_cols
优化方案
核心思路是避免提前将分类转为数字编码,直接基于原始分类标签构建宽表并编码,让OneHotEncoder直接生成带原始标签的列名,无需手动映射:
import pandas as pd from sklearn.preprocessing import OneHotEncoder # 示例数据 data = { 'id': [13,13,14,14,14,15], 'name': ['alex', 'mary', 'alex', 'barry', 'john', 'john'], 'categ': ['dog', 'cat', 'dog', 'ant', 'fox', 'seal'], 'size': ['big', 'small', 'big', 'tiny', 'medium', 'big'] } df = pd.DataFrame(data) # 直接基于原始分类值构建宽表,用'none'作为缺失占位符 piv = df.groupby(['id', 'name'])[['categ', 'size']].first().unstack(fill_value='none') piv.columns = piv.columns.to_flat_index().str.join('_') # 使用OneHotEncoder,直接识别原始分类标签 encoder = OneHotEncoder(sparse_output=True, handle_unknown='ignore') piv_enc = encoder.fit_transform(piv) # 生成带原始标签的列名并构建稀疏DataFrame piv_fin = pd.DataFrame.sparse.from_spmatrix( piv_enc, columns=encoder.get_feature_names_out() ) # 可选:将占位符'none'替换为需求中的'-' piv_fin.columns = piv_fin.columns.str.replace('_none', '_-')
优化说明
- 宽表构建时保留原始分类值,用
'none'替代0作为缺失占位符,确保编码器能识别所有类别 get_feature_names_out()直接生成类似categ_alex_dog、categ_alex_-的列名,完全符合需求- 无需手动维护类别映射字典,彻底省去繁琐的列名修复步骤
内容的提问来源于stack exchange,提问作者Dudelstein
相关产品推荐
相关产品推荐

