为何对OneHot编码后的Female[0]列做Log变换会作用于所有列?
问题:OneHot编码后仅对指定列应用log1p,却多列被变换
我已使用OneHotEncoder对Gender列完成编码,希望仅对编码后的Female[0]列应用log1p变换,但实际编码后的两列都被执行了变换。以下是我的代码、变换前后的数组输出:
代码
import pandas as p from sklearn.preprocessing import FunctionTransformer, OneHotEncoder from sklearn.compose import ColumnTransformer import numpy as n customer=p.read_csv('/content/Customers.csv') customer.drop(['CustomerID','Profession','Family Size','Work Experience'],axis=1,inplace=True) column=ColumnTransformer( [ ('ohe_gender',OneHotEncoder(sparse=False,dtype=n.int32),[0]) ],remainder='passthrough' ) function=ColumnTransformer( [ ('function',FunctionTransformer(n.log1p),[0]) ],remainder='passthrough' ) s=column.fit_transform(customer) function.fit_transform(s)
变换前(OHE编码后)的数组
array([[ 0, 1, 19, 15000, 39], [ 0, 1, 21, 35000, 81], [ 1, 0, 20, 86000, 6], ..., [ 0, 1, 87, 90961, 14], [ 0, 1, 77, 182109, 4], [ 0, 1, 90, 110610, 52]])
变换后的数组
array([[0.00000000e+00, 6.93147181e-01, 1.90000000e+01, 1.50000000e+04, 3.90000000e+01], [0.00000000e+00, 6.93147181e-01, 2.10000000e+01, 3.50000000e+04, 8.10000000e+01], [6.93147181e-01, 0.00000000e+00, 2.00000000e+01, 8.60000000e+04, 6.00000000e+00], ..., [0.00000000e+00, 6.93147181e-01, 8.70000000e+01, 9.09610000e+04, 1.40000000e+01], [0.00000000e+00, 6.93147181e-01, 7.70000000e+01, 1.82109000e+05, 4.00000000e+00], [0.00000000e+00, 6.93147181e-01, 9.00000000e+01, 1.10610000e+05, 5.20000000e+01]]
原因分析
从变换后的数组可以看到,只有OHE生成的前两列被log1p处理,后续列(年龄、收入等)保持原样,说明remainder='passthrough'正常工作。核心问题是:
- 若你的代码确实使用
[0]作为列选择器,理论上仅第0列会被处理,但输出显示第1列也被变换,大概率是代码笔误(比如列选择器误写为[0,1]),或者scikit-learn版本兼容问题导致列选择逻辑异常。 - 另一种可能是你误判了结果:第1列原始值为1时,
log1p(1)=0.693,若代码未选中该列,它应保持原始值1,但你的输出中该列值变为0.693,说明代码确实对第1列也应用了变换。
解决方法
方法1:手动指定列处理(最直接)
跳过ColumnTransformer,直接对numpy数组的目标列进行变换:
s = column.fit_transform(customer) # 仅对第0列应用log1p s[:, 0] = n.log1p(s[:, 0])
方法2:确保ColumnTransformer正确选择列
检查并修正列选择器,同时显式设置FunctionTransformer的validate=True以避免形状错误:
function = ColumnTransformer( [ ('log1p_col0', FunctionTransformer(n.log1p, validate=True), [0]) ], remainder='passthrough' ) result = function.fit_transform(s)
方法3:在Pipeline中组合OHE与log1p变换
将OHE和指定列的log1p变换整合到一个Pipeline中,避免分步处理的错误:
from sklearn.pipeline import Pipeline # 定义Gender列的处理流程:OHE -> 仅对第0列log1p gender_pipeline = Pipeline([ ('ohe', OneHotEncoder(sparse=False, dtype=n.int32)), ('log_col0', ColumnTransformer([ ('log1p', FunctionTransformer(n.log1p), [0]) ], remainder='passthrough')) ]) # 整体预处理流程 preprocessor = ColumnTransformer( [('gender_process', gender_pipeline, [0])], remainder='passthrough' ) result = preprocessor.fit_transform(customer)
内容的提问来源于stack exchange,提问作者Aaftab Tai
相关产品推荐
相关产品推荐

