scikit-learn 中跨多列的标签编码

2024-12-30 08:41:00
admin
原创
42
摘要:问题描述:我正在尝试使用 scikit-learnLabelEncoder来编码 pandasDataFrame字符串标签。由于数据框有很多 (50+) 列,我想避免LabelEncoder为每一列创建一个对象;我宁愿只创建一个LabelEncoder适用于所有数据列的大对象。 将整个DataFrame放入L...

问题描述:

我正在尝试使用 scikit-learnLabelEncoder来编码 pandasDataFrame字符串标签。由于数据框有很多 (50+) 列,我想避免LabelEncoder为每一列创建一个对象;我宁愿只创建一个LabelEncoder适用于所有数据列的大对象。

将整个DataFrame放入LabelEncoder会产生以下错误。请记住,我在这里使用的是虚拟数据;实际上,我正在处理大约 50 列带字符串标签的数据,因此需要一个不按名称引用任何列的解决方案。

import pandas
from sklearn import preprocessing 

df = pandas.DataFrame({
    'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'], 
    'owner': ['Champ', 'Ron', 'Brick', 'Champ', 'Veronica', 'Ron'], 
    'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego', 
                 'New_York']
})

le = preprocessing.LabelEncoder()

le.fit(df)

回溯(最近一次调用最后一次):文件“”,第 1 行,在文件“/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/preprocessing/label.py”,第 103 行,在 fit y = column_or_1d(y,warn=True)文件“/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/utils/validation.py”,第 306 行,在 column_or_1d 中引发 ValueError(“错误输入形状 {0}”。格式(shape))ValueError:错误输入形状(6,3)

关于如何解决这个问题您有什么想法吗?


解决方案 1:

不过你可以轻松地做到这一点,

df.apply(LabelEncoder().fit_transform)

编辑2:

在 scikit-learn 0.20 中,推荐的方式是

OneHotEncoder().fit_transform(df)

因为 OneHotEncoder 现在支持字符串输入。使用 ColumnTransformer 可以将 OneHotEncoder 仅应用于某些列。

编辑:

由于这个原始答案是一年多以前的,并且获得了很多赞成票(包括赏金),我应该进一步扩展它。

对于 inverse_transform 和 transform,您必须做一些修改。

from collections import defaultdict
d = defaultdict(LabelEncoder)

这样,您现在可以将所有列保留LabelEncoder为字典。

# Encoding the variable
fit = df.apply(lambda x: d[x.name].fit_transform(x))

# Inverse the encoded
fit.apply(lambda x: d[x.name].inverse_transform(x))

# Using the dictionary to label future data
df.apply(lambda x: d[x.name].transform(x))

更多编辑:

使用 Neuraxle 的FlattenForEach步骤,也可以这样做,LabelEncoder一次性对所有扁平数据使用相同的方法:

FlattenForEach(LabelEncoder(), then_unflatten=True).fit_transform(df)

对于根据您的数据列使用单独的LabelEncoders,或者如果只有某些数据列需要标签编码而其他数据列不需要,那么使用ColumnTransformer是一种解决方案,可以更好地控制您的列选择和 LabelEncoder 实例。

解决方案 2:

正如 larsmans 所提到的,LabelEncoder() 仅接受一维数组作为参数。也就是说,您可以非常轻松地滚动自己的标签编码器,该编码器对您选择的多个列进行操作并返回转换后的数据框。我这里的代码部分基于 Zac Stewart 的精彩博客文章,可在此处找到。

创建自定义编码器只需创建一个响应 、 和 方法的类即可fit()transform()对于fit_transform()你的情况,一个好的开始可能是这样的:

import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import Pipeline

# Create some toy data in a Pandas dataframe
fruit_data = pd.DataFrame({
    'fruit':  ['apple','orange','pear','orange'],
    'color':  ['red','orange','green','green'],
    'weight': [5,6,3,4]
})

class MultiColumnLabelEncoder:
    def __init__(self,columns = None):
        self.columns = columns # array of column names to encode

    def fit(self,X,y=None):
        return self # not relevant here

    def transform(self,X):
        '''
        Transforms columns of X specified in self.columns using
        LabelEncoder(). If no columns specified, transforms all
        columns in X.
        '''
        output = X.copy()
        if self.columns is not None:
            for col in self.columns:
                output[col] = LabelEncoder().fit_transform(output[col])
        else:
            for colname,col in output.iteritems():
                output[colname] = LabelEncoder().fit_transform(col)
        return output

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

假设我们想对两个分类属性(fruitcolor)进行编码,同时保留数字属性weight。我们可以这样做:

MultiColumnLabelEncoder(columns = ['fruit','color']).fit_transform(fruit_data)

这将我们的fruit_data数据集从

在此处输入图片描述

在此处输入图片描述

向其传递一个完全由分类变量组成的数据框并省略columns参数将导致每一列都被编码(我相信这是您最初寻找的):

MultiColumnLabelEncoder().fit_transform(fruit_data.drop('weight',axis=1))

这将改变

在此处输入图片描述

在此处输入图片描述

请注意,当它尝试对已经是数字的属性进行编码时,它可能会阻塞(如果愿意,可以添加一些代码来处理这个问题)。

另一个很好的特性是,我们可以在管道中使用这个自定义转换器:

encoding_pipeline = Pipeline([
    ('encoding',MultiColumnLabelEncoder(columns=['fruit','color']))
    # add more pipeline steps as needed
])
encoding_pipeline.fit_transform(fruit_data)

解决方案 3:

从 scikit-learn 0.20 开始,您可以使用sklearn.compose.ColumnTransformersklearn.preprocessing.OneHotEncoder

如果只有分类变量,OneHotEncoder则直接:

from sklearn.preprocessing import OneHotEncoder

OneHotEncoder(handle_unknown='ignore').fit_transform(df)

如果您具有异构类型的功能:

from sklearn.compose import make_column_transformer
from sklearn.preprocessing import RobustScaler
from sklearn.preprocessing import OneHotEncoder

categorical_columns = ['pets', 'owner', 'location']
numerical_columns = ['age', 'weigth', 'height']
column_trans = make_column_transformer(
    (categorical_columns, OneHotEncoder(handle_unknown='ignore'),
    (numerical_columns, RobustScaler())
column_trans.fit_transform(df)

文档中的更多选项:http://scikit-learn.org/stable/modules/compose.html#columntransformer-for-heterogeneous-data

解决方案 4:

我们不需要 LabelEncoder。

您可以将列转换为分类,然后获取其代码。我在下面使用了字典理解将此过程应用于每一列,并将结果包装回具有相同索引和列名的相同形状的数据框中。

>>> pd.DataFrame({col: df[col].astype('category').cat.codes for col in df}, index=df.index)
   location  owner  pets
0         1      1     0
1         0      2     1
2         0      0     0
3         1      1     2
4         1      3     1
5         0      2     1

要创建映射字典,您只需使用字典理解来枚举类别:

>>> {col: {n: cat for n, cat in enumerate(df[col].astype('category').cat.categories)} 
     for col in df}

{'location': {0: 'New_York', 1: 'San_Diego'},
 'owner': {0: 'Brick', 1: 'Champ', 2: 'Ron', 3: 'Veronica'},
 'pets': {0: 'cat', 1: 'dog', 2: 'monkey'}}

解决方案 5:

这并没有直接回答你的问题(Naputipulu Jon 和 PriceHardman 对此给出了精彩的回答)

但是,为了完成一些分类任务等,你可以使用

pandas.get_dummies(input_df) 

这可以输入带有分类数据的数据框并返回带有二进制值的数据框。变量值被编码为结果数据框中的列名。更多

解决方案 6:

这是一年半之后的事情了,但我也需要能够.transform()同时处理多个 pandas dataframe 列(并且能够.inverse_transform()同时处理它们)。这扩展了上面 @PriceHardman 的出色建议:

class MultiColumnLabelEncoder(LabelEncoder):
    """
    Wraps sklearn LabelEncoder functionality for use on multiple columns of a
    pandas dataframe.

    """
    def __init__(self, columns=None):
        self.columns = columns

    def fit(self, dframe):
        """
        Fit label encoder to pandas columns.

        Access individual column classes via indexig `self.all_classes_`

        Access individual column encoders via indexing
        `self.all_encoders_`
        """
        # if columns are provided, iterate through and get `classes_`
        if self.columns is not None:
            # ndarray to hold LabelEncoder().classes_ for each
            # column; should match the shape of specified `columns`
            self.all_classes_ = np.ndarray(shape=self.columns.shape,
                                           dtype=object)
            self.all_encoders_ = np.ndarray(shape=self.columns.shape,
                                            dtype=object)
            for idx, column in enumerate(self.columns):
                # fit LabelEncoder to get `classes_` for the column
                le = LabelEncoder()
                le.fit(dframe.loc[:, column].values)
                # append the `classes_` to our ndarray container
                self.all_classes_[idx] = (column,
                                          np.array(le.classes_.tolist(),
                                                  dtype=object))
                # append this column's encoder
                self.all_encoders_[idx] = le
        else:
            # no columns specified; assume all are to be encoded
            self.columns = dframe.iloc[:, :].columns
            self.all_classes_ = np.ndarray(shape=self.columns.shape,
                                           dtype=object)
            for idx, column in enumerate(self.columns):
                le = LabelEncoder()
                le.fit(dframe.loc[:, column].values)
                self.all_classes_[idx] = (column,
                                          np.array(le.classes_.tolist(),
                                                  dtype=object))
                self.all_encoders_[idx] = le
        return self

    def fit_transform(self, dframe):
        """
        Fit label encoder and return encoded labels.

        Access individual column classes via indexing
        `self.all_classes_`

        Access individual column encoders via indexing
        `self.all_encoders_`

        Access individual column encoded labels via indexing
        `self.all_labels_`
        """
        # if columns are provided, iterate through and get `classes_`
        if self.columns is not None:
            # ndarray to hold LabelEncoder().classes_ for each
            # column; should match the shape of specified `columns`
            self.all_classes_ = np.ndarray(shape=self.columns.shape,
                                           dtype=object)
            self.all_encoders_ = np.ndarray(shape=self.columns.shape,
                                            dtype=object)
            self.all_labels_ = np.ndarray(shape=self.columns.shape,
                                          dtype=object)
            for idx, column in enumerate(self.columns):
                # instantiate LabelEncoder
                le = LabelEncoder()
                # fit and transform labels in the column
                dframe.loc[:, column] =\n                    le.fit_transform(dframe.loc[:, column].values)
                # append the `classes_` to our ndarray container
                self.all_classes_[idx] = (column,
                                          np.array(le.classes_.tolist(),
                                                  dtype=object))
                self.all_encoders_[idx] = le
                self.all_labels_[idx] = le
        else:
            # no columns specified; assume all are to be encoded
            self.columns = dframe.iloc[:, :].columns
            self.all_classes_ = np.ndarray(shape=self.columns.shape,
                                           dtype=object)
            for idx, column in enumerate(self.columns):
                le = LabelEncoder()
                dframe.loc[:, column] = le.fit_transform(
                        dframe.loc[:, column].values)
                self.all_classes_[idx] = (column,
                                          np.array(le.classes_.tolist(),
                                                  dtype=object))
                self.all_encoders_[idx] = le
        return dframe.loc[:, self.columns].values

    def transform(self, dframe):
        """
        Transform labels to normalized encoding.
        """
        if self.columns is not None:
            for idx, column in enumerate(self.columns):
                dframe.loc[:, column] = self.all_encoders_[
                    idx].transform(dframe.loc[:, column].values)
        else:
            self.columns = dframe.iloc[:, :].columns
            for idx, column in enumerate(self.columns):
                dframe.loc[:, column] = self.all_encoders_[idx]\n                    .transform(dframe.loc[:, column].values)
        return dframe.loc[:, self.columns].values

    def inverse_transform(self, dframe):
        """
        Transform labels back to original encoding.
        """
        if self.columns is not None:
            for idx, column in enumerate(self.columns):
                dframe.loc[:, column] = self.all_encoders_[idx]\n                    .inverse_transform(dframe.loc[:, column].values)
        else:
            self.columns = dframe.iloc[:, :].columns
            for idx, column in enumerate(self.columns):
                dframe.loc[:, column] = self.all_encoders_[idx]\n                    .inverse_transform(dframe.loc[:, column].values)
        return dframe.loc[:, self.columns].values

例子:

如果dfdf_copy()是混合类型的数据框,则可以按以下方式pandas将应用MultiColumnLabelEncoder()到列:dtype=object

# get `object` columns
df_object_columns = df.iloc[:, :].select_dtypes(include=['object']).columns
df_copy_object_columns = df_copy.iloc[:, :].select_dtypes(include=['object']).columns

# instantiate `MultiColumnLabelEncoder`
mcle = MultiColumnLabelEncoder(columns=object_columns)

# fit to `df` data
mcle.fit(df)

# transform the `df` data
mcle.transform(df)

# returns output like below
array([[1, 0, 0, ..., 1, 1, 0],
       [0, 5, 1, ..., 1, 1, 2],
       [1, 1, 1, ..., 1, 1, 2],
       ..., 
       [3, 5, 1, ..., 1, 1, 2],

# transform `df_copy` data
mcle.transform(df_copy)

# returns output like below (assuming the respective columns 
# of `df_copy` contain the same unique values as that particular 
# column in `df`
array([[1, 0, 0, ..., 1, 1, 0],
       [0, 5, 1, ..., 1, 1, 2],
       [1, 1, 1, ..., 1, 1, 2],
       ..., 
       [3, 5, 1, ..., 1, 1, 2],

# inverse `df` data
mcle.inverse_transform(df)

# outputs data like below
array([['August', 'Friday', '2013', ..., 'N', 'N', 'CA'],
       ['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['August', 'Monday', '2014', ..., 'N', 'N', 'NJ'],
       ..., 
       ['February', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['March', 'Tuesday', '2013', ..., 'N', 'N', 'NJ']], dtype=object)

# inverse `df_copy` data
mcle.inverse_transform(df_copy)

# outputs data like below
array([['August', 'Friday', '2013', ..., 'N', 'N', 'CA'],
       ['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['August', 'Monday', '2014', ..., 'N', 'N', 'NJ'],
       ..., 
       ['February', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
       ['March', 'Tuesday', '2013', ..., 'N', 'N', 'NJ']], dtype=object)

您可以通过索引访问用于适合每列的各个列类、列标签和列编码器:

mcle.all_classes_

mcle.all_encoders_

mcle.all_labels_

解决方案 7:

可以直接在 pandas 中完成所有这些操作,并且非常适合该replace方法的独特能力。

首先,让我们创建一个字典,将列及其值映射到新的替换值。

transform_dict = {}
for col in df.columns:
    cats = pd.Categorical(df[col]).categories
    d = {}
    for i, cat in enumerate(cats):
        d[cat] = i
    transform_dict[col] = d

transform_dict
{'location': {'New_York': 0, 'San_Diego': 1},
 'owner': {'Brick': 0, 'Champ': 1, 'Ron': 2, 'Veronica': 3},
 'pets': {'cat': 0, 'dog': 1, 'monkey': 2}}

由于这始终是一对一的映射,我们可以反转内部字典以获得新值与原始值的映射。

inverse_transform_dict = {}
for col, d in transform_dict.items():
    inverse_transform_dict[col] = {v:k for k, v in d.items()}

inverse_transform_dict
{'location': {0: 'New_York', 1: 'San_Diego'},
 'owner': {0: 'Brick', 1: 'Champ', 2: 'Ron', 3: 'Veronica'},
 'pets': {0: 'cat', 1: 'dog', 2: 'monkey'}}

现在,我们可以利用该方法的独特能力,replace获取嵌套的字典列表,并使用外部键作为列,使用内部键作为我们想要替换的值。

df.replace(transform_dict)
   location  owner  pets
0         1      1     0
1         0      2     1
2         0      0     0
3         1      1     2
4         1      3     1
5         0      2     1

replace我们可以通过再次链接方法轻松回到原始状态

df.replace(transform_dict).replace(inverse_transform_dict)
    location     owner    pets
0  San_Diego     Champ     cat
1   New_York       Ron     dog
2   New_York     Brick     cat
3  San_Diego     Champ  monkey
4  San_Diego  Veronica     dog
5   New_York       Ron     dog

解决方案 8:

不,LabelEncoder不会这样做。它采用 1-d 类标签数组并生成 1-d 数组。它旨在处理分类问题中的类标签,而不是任意数据,任何将其强制用于其他用途的尝试都需要代码将实际问题转换为它要解决的问题(并将解决方案返回到原始空间)。

解决方案 9:

假设您只是想获取一个sklearn.preprocessing.LabelEncoder()可用于表示您的列的对象,您需要做的就是:

le.fit(df.columns)

在上面的代码中,您将获得与每一列相对应的唯一编号。更准确地说,您将拥有 到 的 1:1 映射df.columnsle.transform(df.columns.get_values())要获取列的编码,只需将其传递给le.transform(...)。例如,以下将获取每列的编码:

le.transform(df.columns.get_values())

假设您想sklearn.preprocessing.LabelEncoder()为所有行标签创建一个对象,您可以执行以下操作:

le.fit([y for x in df.get_values() for y in x])

在这种情况下,您很可能拥有非唯一的行标签(如您的问题所示)。要查看编码器创建的类,您可以执行le.classes_。您会注意到,这应该具有与中相同的元素set(y for x in df.get_values() for y in x)。再次将行标签转换为编码标签,请使用le.transform(...)。例如,如果您想检索数组中第一列df.columns和第一行的标签,您可以执行以下操作:

le.transform([df.get_value(0, df.columns[0])])

您在评论中提出的问题有点复杂,但仍然可以完成:

le.fit([str(z) for z in set((x[0], y) for x in df.iteritems() for y in x[1])])

上面的代码执行以下操作:

  1. 对所有 (列,行) 对进行唯一组合

  2. 将每对表示为元组的字符串版本。这是解决类LabelEncoder不支持元组作为类名的解决方法。

  3. 将新物品适合LabelEncoder

现在使用这个新模型有点复杂。假设我们想要提取上一个示例中查找的同一项目的表示(df.columns 中的第一列和第一行),我们可以这样做:

le.transform([str((df.columns[0], df.get_value(0, df.columns[0])))])

请记住,每个查找现在都是包含(列,行)的元组的字符串表示形式。

解决方案 10:

以下是脚本

from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
col_list = df.select_dtypes(include = "object").columns
for colsn in col_list:
    df[colsn] = le.fit_transform(df[colsn].astype(str))

解决方案 11:

如果数据框中同时包含数值和分类两种类型的数据,则可以使用:这里 X 是我的数据框,包含分类和数值两种变量

from sklearn import preprocessing
le = preprocessing.LabelEncoder()

for i in range(0,X.shape[1]):
    if X.dtypes[i]=='object':
        X[X.columns[i]] = le.fit_transform(X[X.columns[i]])

注意:如果您不想将它们转换回来,那么这种技术很有用。

解决方案 12:

经过大量搜索和实验,并在这里和其他地方找到一些答案后,我认为您的答案在这里:

pd.DataFrame(列=df.columns,数据=LabelEncoder()。fit_transform(df.values.flatten())。重塑(df.shape))

这将保留跨列的类别名称:

import pandas as pd
from sklearn.preprocessing import LabelEncoder

df = pd.DataFrame([['A','B','C','D','E','F','G','I','K','H'],
                   ['A','E','H','F','G','I','K','','',''],
                   ['A','C','I','F','H','G','','','','']], 
                  columns=['A1', 'A2', 'A3','A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10'])

pd.DataFrame(columns=df.columns, data=LabelEncoder().fit_transform(df.values.flatten()).reshape(df.shape))

    A1  A2  A3  A4  A5  A6  A7  A8  A9  A10
0   1   2   3   4   5   6   7   9   10  8
1   1   5   8   6   7   9   10  0   0   0
2   1   3   9   6   8   7   0   0   0   0

解决方案 13:

我检查了 LabelEncoder 的源代码(https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/preprocessing/label.py)。它基于一组 numpy 转换,其中之一是 np.unique()。并且此函数仅接受一维数组输入。(如果我错了,请纠正我)。

非常粗略的想法...首先,确定哪些列需要 LabelEncoder,然后循环遍历每一列。

def cat_var(df): 
    """Identify categorical features. 

    Parameters
    ----------
    df: original df after missing operations 

    Returns
    -------
    cat_var_df: summary df with col index and col name for all categorical vars
    """
    col_type = df.dtypes
    col_names = list(df)

    cat_var_index = [i for i, x in enumerate(col_type) if x=='object']
    cat_var_name = [x for i, x in enumerate(col_names) if i in cat_var_index]

    cat_var_df = pd.DataFrame({'cat_ind': cat_var_index, 
                               'cat_name': cat_var_name})

    return cat_var_df



from sklearn.preprocessing import LabelEncoder 

def column_encoder(df, cat_var_list):
    """Encoding categorical feature in the dataframe

    Parameters
    ----------
    df: input dataframe 
    cat_var_list: categorical feature index and name, from cat_var function

    Return
    ------
    df: new dataframe where categorical features are encoded
    label_list: classes_ attribute for all encoded features 
    """

    label_list = []
    cat_var_df = cat_var(df)
    cat_list = cat_var_df.loc[:, 'cat_name']

    for index, cat_feature in enumerate(cat_list): 

        le = LabelEncoder()

        le.fit(df.loc[:, cat_feature])    
        label_list.append(list(le.classes_))

        df.loc[:, cat_feature] = le.transform(df.loc[:, cat_feature])

    return df, label_list

返回的df将是编码后的 df,label_list将显示相应列中所有这些值的含义。这是我为工作编写的数据处理脚本的片段。如果您认为还有进一步改进的空间,请告诉我。

编辑:这里只想提一下,上述方法最适合没有缺失的数据框。不确定它如何处理包含缺失数据的数据框。(在执行上述方法之前,我处理了缺失程序)

解决方案 14:

使用以下方式快捷访问LabelEncoder()多个列dict()

from sklearn.preprocessing import LabelEncoder
le_dict = {col: LabelEncoder() for col in columns }
for col in columns:
    le_dict[col].fit_transform(df[col])

并且您可以使用它le_dict来标记任何其他列:

le_dict[col].transform(df_another[col])

解决方案 15:

LabelEncoder我们可以使用scikit OrdinalEncoder-learn,它允许多列编码。

将分类特征编码为整数数组。此转换器的输入应为整数或字符串数​​组,表示分类(离散)特征所取的值。这些特征将转换为序数整数。这样每个特征将产生一列整数(0 到 n_categories - 1)。

>>> from sklearn.preprocessing import OrdinalEncoder
>>> enc = OrdinalEncoder()
>>> X = [['Male', 1], ['Female', 3], ['Female', 2]]
>>> enc.fit(X)
OrdinalEncoder()
>>> enc.categories_
[array(['Female', 'Male'], dtype=object), array([1, 2, 3], dtype=object)]
>>> enc.transform([['Female', 3], ['Male', 1]])
array([[0., 2.],
       [1., 0.]])

描述和示例均从其文档页面复制而来,您可以在此处找到:

https://scikit-learn.org/stable/modules/ generated/sklearn.preprocessing.OrdinalEncoder.html#sklearn.preprocessing.OrdinalEncoder

解决方案 16:

使用Neuraxle

TLDR;您可以在此处使用FlattenForEach包装器类来简单地转换您的 df,如下所示:FlattenForEach(LabelEncoder(), then_unflatten=True).fit_transform(df)

通过这种方法,你的标签编码器将能够适应并在常规scikit-learn Pipeline中进行转换。我们只需导入:

from sklearn.preprocessing import LabelEncoder
from neuraxle.steps.column_transformer import ColumnTransformer
from neuraxle.steps.loop import FlattenForEach

各列共享相同的编码器:

以下是如何将一个共享的 LabelEncoder 应用于所有数据并对其进行编码:

    p = FlattenForEach(LabelEncoder(), then_unflatten=True)

结果:

    p, predicted_output = p.fit_transform(df.values)
    expected_output = np.array([
        [6, 7, 6, 8, 7, 7],
        [1, 3, 0, 1, 5, 3],
        [4, 2, 2, 4, 4, 2]
    ]).transpose()
    assert np.array_equal(predicted_output, expected_output)

每列不同的编码器:

以下是第一个独立 LabelEncoder 如何应用于宠物,第二个 LabelEncoder 将与所有者和位置列共享。因此,准确地说,我们这里混合了不同的和共享的标签编码器:

    p = ColumnTransformer([
        # A different encoder will be used for column 0 with name "pets":
        (0, FlattenForEach(LabelEncoder(), then_unflatten=True)),
        # A shared encoder will be used for column 1 and 2, "owner" and "location":
        ([1, 2], FlattenForEach(LabelEncoder(), then_unflatten=True)),
    ], n_dimension=2)

结果:

    p, predicted_output = p.fit_transform(df.values)
    expected_output = np.array([
        [0, 1, 0, 2, 1, 1],
        [1, 3, 0, 1, 5, 3],
        [4, 2, 2, 4, 4, 2]
    ]).transpose()
    assert np.array_equal(predicted_output, expected_output)

解决方案 17:

根据@PriceHardman的解决方案所提出的评论,我建议采用以下版本的课程:

class LabelEncodingColoumns(BaseEstimator, TransformerMixin):
def __init__(self, cols=None):
    pdu._is_cols_input_valid(cols)
    self.cols = cols
    self.les = {col: LabelEncoder() for col in cols}
    self._is_fitted = False

def transform(self, df, **transform_params):
    """
    Scaling ``cols`` of ``df`` using the fitting

    Parameters
    ----------
    df : DataFrame
        DataFrame to be preprocessed
    """
    if not self._is_fitted:
        raise NotFittedError("Fitting was not preformed")
    pdu._is_cols_subset_of_df_cols(self.cols, df)

    df = df.copy()

    label_enc_dict = {}
    for col in self.cols:
        label_enc_dict[col] = self.les[col].transform(df[col])

    labelenc_cols = pd.DataFrame(label_enc_dict,
        # The index of the resulting DataFrame should be assigned and
        # equal to the one of the original DataFrame. Otherwise, upon
        # concatenation NaNs will be introduced.
        index=df.index
    )

    for col in self.cols:
        df[col] = labelenc_cols[col]
    return df

def fit(self, df, y=None, **fit_params):
    """
    Fitting the preprocessing

    Parameters
    ----------
    df : DataFrame
        Data to use for fitting.
        In many cases, should be ``X_train``.
    """
    pdu._is_cols_subset_of_df_cols(self.cols, df)
    for col in self.cols:
        self.les[col].fit(df[col])
    self._is_fitted = True
    return self

该类在训练集上拟合编码器,并在转换时使用拟合的版本。代码的初始版本可以在这里找到。

解决方案 18:

如果我们只有一列来进行标签编码及其逆变换,那么当 python 中有多个列时,如何做到这一点就很容易了

def stringtocategory(dataset):
    '''
    @author puja.sharma
    @see The function label encodes the object type columns and gives label      encoded and inverse tranform of the label encoded data
    @param dataset dataframe on whoes column the label encoding has to be done
    @return label encoded and inverse tranform of the label encoded data.
   ''' 
   data_original = dataset[:]
   data_tranformed = dataset[:]
   for y in dataset.columns:
       #check the dtype of the column object type contains strings or chars
       if (dataset[y].dtype == object):
          print("The string type features are  : " + y)
          le = preprocessing.LabelEncoder()
          le.fit(dataset[y].unique())
          #label encoded data
          data_tranformed[y] = le.transform(dataset[y])
          #inverse label transform  data
          data_original[y] = le.inverse_transform(data_tranformed[y])
   return data_tranformed,data_original

解决方案 19:

主要使用@Alexander 的答案,但必须做一些改变 -

cols_need_mapped = ['col1', 'col2']

mapper = {col: {cat: n for n, cat in enumerate(df[col].astype('category').cat.categories)} 
     for col in df[cols_need_mapped]}

for c in cols_need_mapped :
    df[c] = df[c].map(mapper[c])

然后,为了在将来重新使用,您只需将输出保存到 json 文档中,当您需要它时,您可以读取它并使用.map()像我上面所做的那样的函数。

解决方案 20:

import pandas as pd
from sklearn.preprocessing import LabelEncoder

train=pd.read_csv('.../train.csv')

#X=train.loc[:,['waterpoint_type_group','status','waterpoint_type','source_class']].values
# Create a label encoder object 
def MultiLabelEncoder(columnlist,dataframe):
    for i in columnlist:

        labelencoder_X=LabelEncoder()
        dataframe[i]=labelencoder_X.fit_transform(dataframe[i])
columnlist=['waterpoint_type_group','status','waterpoint_type','source_class','source_type']
MultiLabelEncoder(columnlist,train)

在这里,我从位置读取一个 csv,并在函数中传递我想要标记编码的列表和我想要应用它的数据框。

解决方案 21:

如果您具有对象类型的所有功能,那么上面写的第一个答案就可以很好地发挥作用https://stackoverflow.com/a/31939145/5840973

但是,假设我们有混合类型的列。那么我们可以以编程方式获取对象类型的特征名称列表,然后对其进行标签编码。

#Fetch features of type Object
objFeatures = dataframe.select_dtypes(include="object").columns

#Iterate a loop for features of type object
from sklearn import preprocessing
le = preprocessing.LabelEncoder()

for feat in objFeatures:
    dataframe[feat] = le.fit_transform(dataframe[feat].astype(str))
 

dataframe.info()

解决方案 22:

问题在于您传递给 fit 函数的数据 (pd 数据框) 的形状。您必须传递 1d 列表。

解决方案 23:

这个怎么样?

def MultiColumnLabelEncode(choice, columns, X):
    LabelEncoders = []
    if choice == 'encode':
        for i in enumerate(columns):
            LabelEncoders.append(LabelEncoder())
        i=0    
        for cols in columns:
            X[:, cols] = LabelEncoders[i].fit_transform(X[:, cols])
            i += 1
    elif choice == 'decode': 
        for cols in columns:
            X[:, cols] = LabelEncoders[i].inverse_transform(X[:, cols])
            i += 1
    else:
        print('Please select correct parameter "choice". Available parameters: encode/decode')

它不是最有效的,但它有效并且非常简单。

解决方案 24:

这是我对您的问题的解决方案。为了将包含文本的数据框列转换为编码值,只需使用我的函数 text_to_numbers,它会返回 LE 的字典。键是列LabelEncoder()作为值的列名。

def text_to_numbers(df):
        le_dict = dict()
        for i in df.columns:
            if df[i].dtype not in ["float64", "bool", "int64"]:
                le_dict[i] = preprocessing.LabelEncoder()
                df[i] = le_dict[i].fit_transform(df[i])
    
        return df, le_dict

下面的函数可以保留原始未编码的数据框。

 def numbers_to_text(df, le_dict):
        for i in le_dict.keys():
            df[i] = le_dict[i].inverse_transform(df[i])
    
        return df

解决方案 25:

这是我一次性转换多列的解决方案,以及准确的逆变换

from sklearn import preprocessing
columns = ['buying','maint','lug_boot','safety','cls']  # columns names where transform is required
for X in columns:
  exec(f'le_{X} = preprocessing.LabelEncoder()')  #create label encoder with name "le_X", where X is column name
  exec(f'df.{X} = le_{X}.fit_transform(df.{X})')  #execute fit transform for column X with respective lable encoder "le_X", where X is column name
df.head()  # to display transformed results

for X in columns:
  exec(f'df.{X} = le_{X}.inverse_transform(df.{X})')  #execute inverse_transform for column X with respective lable encoder "le_X", where X is column name
df.head() # to display Inverse transformed results of df
相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   997  
  在项目管理领域,CDCP(Certified Data Center Professional)认证评审是一个至关重要的环节,它不仅验证了项目团队的专业能力,还直接关系到项目的成功与否。在这一评审过程中,沟通技巧的运用至关重要。有效的沟通不仅能够确保信息的准确传递,还能增强团队协作,提升评审效率。本文将深入探讨CDCP...
华为IPD流程   34  
  IPD(Integrated Product Development,集成产品开发)是一种以客户需求为核心、跨部门协同的产品开发模式,旨在通过高效的资源整合和流程优化,提升产品开发的成功率和市场竞争力。在IPD培训课程中,掌握关键成功因素是确保团队能够有效实施这一模式的核心。以下将从五个关键成功因素展开讨论,帮助企业和...
IPD项目流程图   40  
  华为IPD(Integrated Product Development,集成产品开发)流程是华为公司在其全球化进程中逐步构建和完善的一套高效产品开发管理体系。这一流程不仅帮助华为在技术创新和产品交付上实现了质的飞跃,还为其在全球市场中赢得了显著的竞争优势。IPD的核心在于通过跨部门协作、阶段性评审和市场需求驱动,确保...
华为IPD   39  
  华为作为全球领先的通信技术解决方案提供商,其成功的背后离不开一套成熟的管理体系——集成产品开发(IPD)。IPD不仅是一种产品开发流程,更是一种系统化的管理思想,它通过跨职能团队的协作、阶段评审机制和市场需求驱动的开发模式,帮助华为在全球市场中脱颖而出。从最初的国内市场到如今的全球化布局,华为的IPD体系在多个领域展现...
IPD管理流程   71  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用