如何将 OneHotEncoder 用于多列并自动删除每列的第一个虚拟变量?

Posted

技术标签:

【中文标题】如何将 OneHotEncoder 用于多列并自动删除每列的第一个虚拟变量?【英文标题】:How to use OneHotEncoder for multiple columns and automatically drop first dummy variable for each column? 【发布时间】:2017-11-19 22:57:06 【问题描述】:

这是包含 3 列和 3 行的数据集

命名组织部门

Manie ABC2 财经

乔伊斯 ABC1 HR

阿米 NSV2 人力资源

这是我的代码:

现在到这里都很好,我如何删除每个虚拟变量列的第一个?

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Importing the dataset
dataset = pd.read_csv('Data1.csv',encoding = "cp1252")
X = dataset.values


# Encoding categorical data
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
labelencoder_X_0 = LabelEncoder()
X[:, 0] = labelencoder_X_0.fit_transform(X[:, 0])
labelencoder_X_1 = LabelEncoder()
X[:, 1] = labelencoder_X_1.fit_transform(X[:, 1])
labelencoder_X_2 = LabelEncoder()
X[:, 2] = labelencoder_X_2.fit_transform(X[:, 2])

onehotencoder = OneHotEncoder(categorical_features = "all")
X = onehotencoder.fit_transform(X).toarray()

【问题讨论】:

pandas 有get_dummies(),它有一个参数drop_first 你可以设置为True。下面是一个使用 get_dummies 的例子:***.com/a/43971156/1870832 Hey Max Power,我试过 X = pd.get_dummies(X, drop_first=True)),但它显​​示错误 SyntaxError: invalid syntax 在下面查看我的答案并测试输出。我猜你的语法错误来自你代码的另一部分。 你的 X 来自 read_csv 作为 Pandas DatafFrame。尝试将dataset 传递给pd.get_dummies(),然后再使用.values。如果你希望 one-hot-encoded 输出是一个 numpy 数组,你可以取 .values 的输出 pd.get_dummies 查看我的更新答案。抱歉耽搁了,我想我们在不同的时区,我睡着了。 【参考方案1】:
import pandas as pd
df = pd.DataFrame('name': ['Manie', 'Joyce', 'Ami'],
                   'Org':  ['ABC2', 'ABC1', 'NSV2'],
                   'Dept': ['Finance', 'HR', 'HR']        
        )


df_2 = pd.get_dummies(df,drop_first=True)

测试:

print(df_2)
   Dept_HR  Org_ABC2  Org_NSV2  name_Joyce  name_Manie
0        0         1         0           0           1
1        1         0         0           1           0
2        1         0         1           0           0 

更新您在pd.get_dummies(X, columns =[1:] 中的错误:

根据documentation page,columns 参数采用“列名称”。所以下面的代码可以工作:

df_2 = pd.get_dummies(df, columns=['Org', 'Dept'], drop_first=True)

输出:

    name  Org_ABC2  Org_NSV2  Dept_HR
0  Manie         1         0        0
1  Joyce         0         0        1
2    Ami         0         1        1

如果你真的想在位置上定义你的列,你可以这样做:

column_names_for_onehot = df.columns[1:]
df_2 = pd.get_dummies(df, columns=column_names_for_onehot, drop_first=True)

【讨论】:

【参考方案2】:

我使用自己的模板:

from sklearn.base import TransformerMixin
import pandas as pd
import numpy as np
class DataFrameEncoder(TransformerMixin):

    def __init__(self):
        """Encode the data.

        Columns of data type object are appended in the list. After 
        appending Each Column of type object are taken dummies and 
        successively removed and two Dataframes are concated again.

        """
    def fit(self, X, y=None):
        self.object_col = []
        for col in X.columns:
            if(X[col].dtype == np.dtype('O')):
                self.object_col.append(col)
        return self

    def transform(self, X, y=None):
        dummy_df = pd.get_dummies(X[self.object_col],drop_first=True)
        X = X.drop(X[self.object_col],axis=1)
        X = pd.concat([dummy_df,X],axis=1)
        return X

为了使用此代码,只需将此模板放在当前目录中,文件名为 CustomeEncoder.py 并输入您的代码:

from customEncoder import DataFrameEncoder
data = DataFrameEncoder().fit_transormer(data)

所有的对象类型数据都被移除、编码、移除并连接在一起,以提供最终所需的输出。 PS:这个模板的输入文件是 Pandas Dataframe。

【讨论】:

【参考方案3】:

从 0.21 开始的 scikit-learn 版本非常简单。可以使用 OneHotEncoder 中的 drop 参数并使用它来删除每个特征的类别之一。默认情况下,它不会下降。详细信息可以在文档中找到。

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

//drops the first category in each feature
ohe = OneHotEncoder(drop='first', handle_unknown='error')

【讨论】:

【参考方案4】:

我使用自己的模块来处理一种热编码。

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

class My_encoder(BaseEstimator, TransformerMixin):
   
    def __init__(self,drop = 'first',sparse=False):
        self.encoder = OneHotEncoder(drop = drop,sparse = sparse)
        self.features_to_encode = []
        self.columns = []
    
    def fit(self,X_train,features_to_encode):
        
        data = X_train.copy()
        self.features_to_encode = features_to_encode
        data_to_encode = data[self.features_to_encode]
        self.columns = pd.get_dummies(data_to_encode,drop_first = True).columns
        self.encoder.fit(data_to_encode)
        return self.encoder
    
    def transform(self,X_test):
        
        data = X_test.copy()
        data.reset_index(drop = True,inplace =True)
        data_to_encode = data[self.features_to_encode]
        data_left = data.drop(self.features_to_encode,axis = 1)
        
        data_encoded = pd.DataFrame(self.encoder.transform(data_to_encode),columns = self.columns)
        
        return pd.concat([data_left,data_encoded],axis = 1)

它很容易使用

features_to_encode = [---list of features to one hot encode--]
enc = My_encoder()
enc.fit(X_train,features_to_encode)
X_train = enc.transform(X_train)
X_test = enc.transform(X_test)

它返回带有列名的数据框。因此,涵盖了 OneHotEncoder 和 pd.get_dummies() 的缺点。 因此,我们可以使用它来拟合和转换,就像 OneHotEncoder 一样,它还可以为我们保存列名并返回一个类似于假人的数据帧方法。

【讨论】:

【参考方案5】:

一次编码一个分类变量。虚拟变量应该转到数据集的开始索引。然后,像这样剪掉第一列:

X = X[:, 1:]

然后编码并重复下一个变量。

【讨论】:

【参考方案6】:

使用 ColumnTransformer 可以仅将 OneHotEncoder 应用于某些列。 为分类变量和数值变量创建单独的管道并应用 ColumnTransformer。有关它的更多信息可以在这里找到ColumnTransformer。

here 提供了另一个很好的实现示例。

【讨论】:

请在此处自己写下答案的相关部分,因为链接可能会随着时间而改变。【参考方案7】:
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
for i in range(Y.shape[1]):
    Y[:,i] = le.fit_transform(Y[:,i])

【讨论】:

欢迎来到 SO。不鼓励仅使用代码的答案。还请提供一些背景信息。 请提供解释,以便其他人能够理解您的代码,并了解它如何解决问题。

以上是关于如何将 OneHotEncoder 用于多列并自动删除每列的第一个虚拟变量?的主要内容,如果未能解决你的问题,请参考以下文章

OneHotEncoder 多列

将 OneHotEncoder 用于决策树分类器中的分类特征

LabelEncoder 和OneHotEncoder

如何在 sklearn 中使用 OneHotEncoder 的输出?

Excel合并多列单元格并自动换行

如何改进此代码以使用 OneHotEncoder? [复制]