You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

长表转宽表稀疏矩阵后,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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 10:07:44