如何在Scikit-learn ColumnTransformer管道中动态传递留存数值列?
问题解答
可行,但不能直接在ColumnTransformer的列参数里写列表推导式——因为ColumnTransformer初始化时就会固定列集合,不会自动根据前面步骤的输出动态调整列。要实现你要的效果,得用动态列选择的方式,下面是两种具体的实现方案:
方案一:自定义动态列选择Transformer
写一个简单的自定义Transformer,专门用来筛选当前数据中属于num_cols的列,把它放到numeric_transformer的最前面,这样后续的imputer和scaler只会处理剩下的有效列:
from sklearn.base import BaseEstimator, TransformerMixin class DynamicNumericSelector(BaseEstimator, TransformerMixin): def __init__(self, num_cols): self.num_cols = num_cols def fit(self, X, y=None): return self def transform(self, X): # 筛选出当前X中存在的num_cols列 valid_cols = [col for col in self.num_cols if col in X.columns] return X[valid_cols] # 修改numeric_transformer,加入动态列选择步骤 numeric_transformer = Pipeline(steps=[ ('selector', DynamicNumericSelector(num_cols)), # 新增步骤 ('imputer', SimpleImputer(strategy = "constant", fill_value=-1, add_indicator=True)), ('scaler', StandardScaler()) ]) # 后续的ColumnTransformer和pipeline保持不变,numeric部分直接用这个新的transformer preprocess_ppl = ColumnTransformer( transformers=[ ('categorical', categorical_transformer, ['MARITAL_STATUS']), ('zero_impute', fill_na_zero_transformer, fill_zero_cols), ('numeric', numeric_transformer, slice(None)) # 这里用slice(None)表示传入所有列,交给selector筛选 ] )
方案二:利用ColumnTransformer的Callable列选择器(Scikit-learn 0.24+)
从Scikit-learn 0.24版本开始,ColumnTransformer的列参数支持传入可调用对象(callable),这个函数会接收当前的输入数据X,返回要处理的列名列表。直接用这个特性更简洁:
# 定义动态列选择函数 def select_valid_numeric_cols(X): return [col for col in num_cols if col in X.columns] # 修改ColumnTransformer中的numeric部分,列参数传入这个函数 preprocess_ppl = ColumnTransformer( transformers=[ ('categorical', categorical_transformer, ['MARITAL_STATUS']), ('zero_impute', fill_na_zero_transformer, fill_zero_cols), ('numeric', numeric_transformer, select_valid_numeric_cols) # 直接传函数 ] ) # 后续pipeline保持不变
注意事项
- 方案二需要确保你的Scikit-learn版本≥0.24,版本过低的话建议用方案一;
- 如果
fill_zero_cols也存在被前面步骤删除的情况,同样可以用上述方法处理; - 自定义Transformer时要确保符合Scikit-learn的API规范(继承
BaseEstimator和TransformerMixin,实现fit和transform方法)。
内容的提问来源于stack exchange,提问作者Obiii
相关产品推荐
相关产品推荐

