ColumnTransformer设remainder='passthrough'时报字符串转浮点错误
问题原因
remainder='passthrough'本身是正常生效的,确实原样透传了未指定处理规则的da列,报错来自后续结果拼接环节,核心触发逻辑如下:
- 你使用的
OneHotEncoder默认输出稀疏矩阵,当ColumnTransformer检测到任意一个转换分支输出稀疏矩阵时,会默认尝试把所有分支的输出(包括透传的未处理列)统一转换为稀疏矩阵后再做横向拼接。 - 透传的
da列是字符串格式的日期值,无法转换为稀疏矩阵要求的浮点数值类型,因此触发类型转换错误。
另外你代码中提前定义了int_columns、obj_columns做列类型筛选,但后续配置ColumnTransformer时完全没有使用这两个变量,而是硬编码了处理列名,直接漏掉了da列的处理逻辑,也是导致问题的诱因。
修复方案
方案1:正确处理日期列(推荐,适配后续建模需求)
不要直接透传字符串格式的日期列,先将其转换为日期类型提取可用的数值特征,再纳入预处理管道,所有特征处理后均为数值类型,从根源避免类型冲突。
参考代码如下:
import pandas as pd import numpy as np from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.compose import ColumnTransformer # 处理日期列,提取可用于建模的数值特征(也可自定义转换器封装到管道内) _d['da'] = pd.to_datetime(_d['da']) _d['da_month'] = _d['da'].dt.month x = _d.drop(['target', 'da'], axis=1) # 删除原始字符串日期列 y = _d['target'] # 复用之前的列类型筛选逻辑,避免硬编码漏列 int_columns = x.select_dtypes(['float64','int64']).columns.tolist() cat_columns = x.select_dtypes(['object','category']).columns.tolist() int_pipeline=Pipeline([ ('impute_values',SimpleImputer(missing_values=np.nan,strategy='mean')), ('scaling',StandardScaler()) ]) cat_pipeline=Pipeline([ ('cat_impute',SimpleImputer(strategy='constant',fill_value='missing')), # sklearn 1.2以下版本将sparse_output改为sparse即可 ('encoding',OneHotEncoder(drop='first', sparse_output=False)) ]) # 所有列都分配对应处理逻辑,不需要额外设置remainder column_trans=ColumnTransformer(transformers=[ ('int_p',int_pipeline,int_columns), ('cat_p',cat_pipeline,cat_columns) ]) mdl_pipeline=Pipeline([ ('value_transform',column_trans) ]) transformed_data=mdl_pipeline.fit_transform(x,y)
方案2:关闭OneHotEncoder稀疏输出(仅临时调试用)
如果只是临时调试预处理流程,可以关闭OneHotEncoder的稀疏输出,此时ColumnTransformer会拼接普通稠密数组,不会强制转换透传列的类型:
cat_pipeline=Pipeline([ ('cat_impute',SimpleImputer(strategy='constant',fill_value='missing')), ('encoding',OneHotEncoder(drop='first', sparse_output=False)) ])
注意:该方案处理后的数据中da列仍为字符串类型,后续传入机器学习模型时会继续报错,仅适合流程调试使用。
方案3:调整ColumnTransformer稀疏阈值(不推荐)
给ColumnTransformer传入sparse_threshold=0参数强制输出稠密矩阵,效果和方案2类似,会丧失稀疏矩阵节省内存的优势,且同样没有解决日期列为字符串无法建模的问题:
column_trans=ColumnTransformer(transformers=[ ('int_p',int_pipeline,['ind', 'score']), ('cat_p',cat_pipeline,['grade', 'group']) ],remainder='passthrough', sparse_threshold=0)
内容的提问来源于stack exchange,提问作者Lijin Durairaj
相关产品推荐
相关产品推荐

