首页 > 解决方案 > 有没有办法在 sklearn 管道中链接 pd.cut FunctionTransformer?

问题描述

我正在使用 sklearn 制作 DataFrame 预处理管道并链接各种类型的预处理步骤。

我想链接一个SimpleImputer变压器并FunctionTransformer应用一个pd.qcut(或pd.cut),但我不断收到以下错误:

ValueError:输入数组必须是一维的

这是我的代码:

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import FunctionTransformer

class FeatureSelector(BaseEstimator, TransformerMixin):
    def __init__(self, features):
        self._features = features

    def fit(self, X, y=None):
        return self

    def transform(self, X, y=None):
        return X[self._features]

fare_transformer = Pipeline([
    ('fare_selector', FeatureSelector(['Fare'])),
    ('fare_imputer', SimpleImputer(strategy='median')),
    ('fare_bands', FunctionTransformer(func=pd.qcut, kw_args={'q': 5}))
])

如果我简单地将FeatureSelector变压器和FunctionTransformerwith链接起来pd.qcut并省略SimpleImputer:

fare_transformer = Pipeline([
    ('fare_selector', FeatureSelector(['Fare'])),
    ('fare_bands', FunctionTransformer(func=pd.qcut, kw_args={'q': 5}))
])

我广泛搜索了 stackoverflow 和 google,但找不到解决此问题的方法。这里的任何帮助将不胜感激!

标签: pythonpandasscikit-learnpipeline

解决方案


sklearn 已经有这样的转换器,KBinsDiscretizer(匹配pd.qcut,使用strategy='quantile')。它将主要在transform测试数据的方式上有所不同:FunctionTransformer版本将“重新调整”分位数,而内置KBinsDiscretizer将保存分位数统计信息以对测试数据进行分箱。正如@m_power 在评论中指出的那样,它们在 bin 边缘附近以及转换后数据的格式也不同。

但要具体解决该错误:这意味着您的函数qcut仅适用于一维数组,而FunctionTransformer发送整个数据帧。您可以定义一个薄包装器qcut来完成这项工作,比如

def frame_qcut(X, y=None, q=10):
    return X.apply(pd.qcut, axis=0, q=q)

(假设您将获得一个数据框。)


推荐阅读