如何在scikit-learn中通过ColumnTransformer对同一列应用多个变换
问题背景
我有一个异构DataFrame,所用数据集来自Kaggle的IEE Fraud Detection数据集,示例如下:
我使用ColumnTransformer实现多步特征变换,代码如下:
# merging transformations into one pipeline with columntransformer process_pipe = ColumnTransformer( [ ( "most_frequent_imputer", PandasSimpleImputer(strategy="most_frequent"), impute_freq ), ( "aggregate_high_cardinality_features", AggregateCategorical(high_cardinality_cats), high_cardinality_cats ), ( "get_categorical_codes", FunctionTransformer(convert_to_category), cat_codes_cols ), ( "mean_imputer", PandasSimpleImputer(strategy="mean"), continuous_features ) ], remainder="passthrough", verbose_feature_names_out=False )
注:PandasSimpleImputer是自定义的封装类,可让sklearn的SimpleImputer返回pandas DataFrame;AggregateCategorical是自定义的类,用于降低高基数特征的类别数量。
问题描述
ColumnTransformer运行时会为每步变换的输出列添加变换名前缀,若需要对部分特征串行执行多步变换(例如先填充缺失值,再生成分类编码),当前管道中填充后生成的新列不会被后续变换调用,后续步骤仍读取原始特征进行处理,不符合预期。
手动给多步处理的特征名加上对应前缀匹配变换后列名再删除冗余列的方案人工操作量很大,有没有更高效的实现方法?
高效实现方案
对需要串行执行多步变换的同组特征,先将多个变换步骤封装为独立的Pipeline,再将该Pipeline作为ColumnTransformer的单个变换项绑定到对应列即可,示例代码如下:
from sklearn.pipeline import Pipeline # 对需要串行处理的特征组单独定义变换管道 # 示例:需要先众数填充、再聚合高基数类别、再转分类编码的特征组 cat_process_pipe = Pipeline( steps=[ ("most_frequent_imputer", PandasSimpleImputer(strategy="most_frequent")), ("aggregate_high_cardinality", AggregateCategorical(high_cardinality_cats)), ("get_categorical_codes", FunctionTransformer(convert_to_category)) ] ) # 把封装好的串行管道作为单步放入ColumnTransformer process_pipe = ColumnTransformer( [ ("categorical_process", cat_process_pipe, cat_codes_cols), # 对应需要多步处理的分类特征列 ("mean_imputer", PandasSimpleImputer(strategy="mean"), continuous_features) # 单步处理的连续特征列 ], remainder="passthrough", verbose_feature_names_out=False )
方案优势
- 不需要手动处理列名前缀:同一Pipeline内的变换步骤默认基于上一步的输出结果执行,完全适配自定义的返回DataFrame的变换类,列名会按Pipeline的最后一步输出自动处理
- 可维护性高:后续需要调整某类特征的变换逻辑时,只修改对应子Pipeline的步骤即可,不需要调整ColumnTransformer的整体结构
- 没有冗余列生成:同组特征的多步变换只会输出最终处理后的列,不会产生中间冗余列,不需要额外做列删除操作
内容的提问来源于stack exchange,提问作者Kurtis Pykes
相关产品推荐
相关产品推荐

