scikit-learn 转换器,根据用户提供的切割点对数据进行分箱

Ste*_*mer 5 python numpy pandas scikit-learn sklearn-pandas

我正在尝试在 scikit-learn 管道中包含一个转换器,它将根据我自己提供的切割点将连续数据列分为 4 个值。KBinsDiscretizer的当前参数不起作用主要是因为该strategy参数只接受{‘uniform’, ‘quantile’, ‘kmeans’}.

pandas 中已经有这个cut()函数,所以我想我需要创建一个包含函数行为的自定义转换器。cut()

期望的行为(非实际)

X = [[-2, -1, -0.5, 0, 0.5, 1, 2]]
est = Discretizer(bins=[-float("inf"), -1.0, 0.0, 1.0, float("inf")], 
                  encode='ordinal')
est.fit(X)  
est.transform(X)
# >>> array([[0., 0., 1., 1., 2., 2., 3.]])
Run Code Online (Sandbox Code Playgroud)

上面的结果假设 bin 包括最右边的边缘并包括最低的边缘。像这个pd.cut()命令将提供:

import pandas as pd
import numpy as np
pd.cut(np.array([-2, -1, -0.5, 0, 0.5, 1, 2]),
       [-float("inf"), -1.0, 0.0, 1.0, float("inf")], 
       labels=False, right=True, include_lowest=True)
# >>> array([0, 0, 1, 1, 2, 2, 3])
Run Code Online (Sandbox Code Playgroud)

Ste*_*mer 1

作为自定义变压器,这似乎对我有用。scikit-learn需要数字数组,所以我不确定您是否可以实现pd.cut()返回标签的功能。因此,我将其硬编码到False下面的实现中。

import pandas as pd
from sklearn.base import BaseEstimator, TransformerMixin

class CutTransformer(BaseEstimator, TransformerMixin):
    def __init__(self, bins, right=True, retbins=False,
                 precision=3, include_lowest=False,
                 duplicates='raise'):
        self.bins = bins
        self.right = right
        self.labels = False
        self.retbins = retbins
        self.precision = precision
        self.include_lowest = include_lowest
        self.duplicates = duplicates

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

    def transform(self, X, y=None):
        assert isinstance(X, pd.DataFrame)
        for jj in range(X.shape[1]):
            X.iloc[:, jj] = pd.cut(x=X.iloc[:, jj].values, **self.__dict__)
        return X
Run Code Online (Sandbox Code Playgroud)

一个例子

df = pd.DataFrame(data={'rand': np.random.rand(5)})
df
    rand
0   0.030653
1   0.542533
2   0.159646
3   0.963112
4   0.539530

ct = CutTransformer(bins=np.linspace(0, 1, 5))
ct.transform(df)
    rand
0   0
1   2
2   0
3   3
4   2
Run Code Online (Sandbox Code Playgroud)