【问题标题】:LabelEncoder with ordered encoding具有有序编码的 LabelEncoder
【发布时间】:2020-10-29 07:00:58
【问题描述】:

我正在使用标签编码器

data = [[1,'A'],
        [1,'A'],
        [1,'B'],
        [2,'C']]

le = LabelEncoder()
df = pd.DataFrame(data = data,columns = ['id','element'])
df['element'] = le.fit_transform(df['element'])

输出

   id  element
0   1        0
1   2        0
2   3        1
3   4        2

这很好,但如果我有很多数据,那么序列就会像这样混合起来

   id  element
0   1       1
1   2       1
2   3       2
3   4       0

任何不带标签编码器的解决方案,以确保保持序列

【问题讨论】:

    标签: python python-3.x pandas scikit-learn


    【解决方案1】:

    TL;DR:对于一个简单的方法,pd.factorize。尽管对于使用通常的 scikit-learn fit/transform 方法 OrderedLabelEncoder 的方法进行了定义,但它只是重写了两个基类的方法以获得编码,其中代码按类的出现顺序排序。


    object dtype 列中的类在LabelEncoder 中按字典顺序排序,这导致生成的代码显示为无序。这可以在_encode_python 中看到,它在fit 方法中被调用。其中,当dtype 列是object 时,classes 变量(然后用于映射值)通过采用set 来定义。一个明显的例子,可能是(复制_encode_python 中所做的):

    df = pd.DataFrame([[1,'C'],[1,'C'],[1,'B'],[2,'A']], columns=['id','element'])
    values = df.element.to_numpy()
    # array(['C', 'C', 'B', 'A'], dtype=object)
    uniques = sorted(set(values))
    uniques = np.array(uniques, dtype=values.dtype)
    table = {val: i for i, val in enumerate(uniques)}
    print(table)
    {'A': 0, 'B': 1, 'C': 2}
    

    生成的set 用于定义一个查找表,该表将确定特征的顺序。

    因此,在这种情况下,我们会得到:

    ole = LabelEncoder()
    ole.fit_transform(df.element)
    # array([2, 2, 1, 0])
    

    对于一个简单的替代方案,您有 pd.factorize,它将保持顺序:

    df['element'] = pd.factorize(df.element)[0]
    

    尽管如果您需要一个具有通常 scikit-learn fit/transform 方法的类,我们可以重新定义定义类的特定函数,并提出一个保持外观顺序的等价物。一种简单的方法是,使用uniques = list(dict.fromkeys(values)) 将列值设置为字典键(维护 Python >3.7 的插入顺序):

    def ordered_encode_python(values, uniques=None, encode=False):
        # only used in _encode below, see docstring there for details
        if uniques is None:
            uniques = list(dict.fromkeys(values))
            uniques = np.array(uniques, dtype=values.dtype)
        if encode:
            table = {val: i for i, val in enumerate(uniques)}
            try:
                encoded = np.array([table[v] for v in values])
            except KeyError as e:
                raise ValueError("y contains previously unseen labels: %s"
                                 % str(e))
            return uniques, encoded
        else:
            return uniques
    

    那么我们可以从LabelEncoder继承并将OrderedLabelEncoder定义为:

    from sklearn.preprocessing import LabelEncoder
    from sklearn.utils.validation import column_or_1d
    
    class OrderedLabelEncoder(LabelEncoder):
        def fit(self, y):
            y = column_or_1d(y, warn=True)
            self.classes_ = ordered_encode_python(y)
        def fit_transform(self, y):
            y = column_or_1d(y, warn=True)
            self.classes_, y = ordered_encode_python(y, encode=True)
            return y 
    

    然后可以像LabelEncoder 一样继续,例如:

    ole = OrderedLabelEncoder()
    ole.fit(df.element)
    ole.classes_
    # array(['C', 'B', 'A'], dtype=object)
    ole.transform(df.element)
    # array([0, 0, 1, 2])
    ole.inverse_transform(np.array([0, 0, 1, 2]))
    # array(['C', 'C', 'B', 'A'], dtype=object)
    

    或者我们也可以拨打fit_transform

    ole.fit_transform(df.element)
    # array([0, 0, 1, 2])
    

    【讨论】:

      猜你喜欢
      • 2018-12-20
      • 2018-09-23
      • 2021-01-21
      • 2021-01-26
      • 2017-01-31
      • 2020-03-04
      • 2019-08-19
      • 2021-09-13
      • 2021-04-21
      相关资源
      最近更新 更多