一种热编码训练,其值不存在于测试中

7 python pandas scikit-learn

我有一个存储为数据帧的训练和测试集。我正在尝试对我的数据集上的标称特征进行 One-hot 编码。但我有以下问题:

  1. 总共有 3 个分类特征,但我不知道每个特征的值是多少,因为数据集很大。
  2. 测试集具有训练集上不存在的值,因此当我进行单热编码时,训练集应该将向量标记为 0 以表示不可见的值。但正如我在 1 中提到的,我不知道所有的功能。
  3. 我发现我可以df = pd.get_dummies(df, prefix_sep='_')用来做一个热编码,该命令适用于所有分类特征,但我注意到它将新特征移到了训练 DataFrame 的末尾,我认为这是一个问题,因为我们不知道哪个特征的索引。还有第 2 个问题,新的火车/集合应该具有相同的索引。

有没有自动的方法来做到这一点?或者图书馆?

编辑

由于下面的答案,我能够对许多功能执行一种热编码。但是下面的代码给出了以下问题:

  1. 我认为scikit-learn剥离列标题并将结果生成为数组而不是数据帧
  2. 由于特征被剥离,我们不知道哪个向量属于哪个特征。即使我执行df_scaled = pd.DataFrame(ct.fit_transform(data2))将结果存储在数据帧中,创建的数据帧df_scaled也没有标题,尤其是在预处理后标题现在更改时。也许sklearn.preprocessing.OneHotEncoder有一种方法可以跟踪新功能及其索引?

Max*_*Kan 8

而不是使用pd.get_dummies,它有你发现的缺点,使用sklearn.preprocessing.OneHotEncoder. 它会自动从您的训练数据中获取所有名义类别,然后根据训练步骤中确定的类别对您的测试数据进行编码。如果测试数据中有新类别,它只会将您的数据编码为 0。

例子:

from sklearn.preprocessing import OneHotEncoder
import numpy as np

x_train = np.array([["A1","B1","C1"],["A2","B1","C2"]])
x_test = np.array([["A1","B2","C2"]]) # As you can see, "B2" is a new attribute for column B

ohe = OneHotEncoder(handle_unknown = 'ignore') #ignore tells the encoder to ignore new categories by encoding them with 0's
ohe.fit(x_train)
print(ohe.transform(x_train).toarray())
>>> array([[1., 0., 1., 1., 0.],
           [0., 1., 1., 0., 1.]])
Run Code Online (Sandbox Code Playgroud)

要按训练集中的列获取类别的摘要,请执行以下操作:

print(ohe.categories_)
>>> [array(['A1', 'A2'], dtype='<U2'), 
     array(['B1'], dtype='<U2'), 
     array(['C1', 'C2'], dtype='<U2')]
Run Code Online (Sandbox Code Playgroud)

要将一个热编码列映射到类别,请执行以下操作:

print(ohe.get_feature_names())
>>> ['x0_A1' 'x0_A2' 'x1_B1' 'x2_C1' 'x2_C2']
Run Code Online (Sandbox Code Playgroud)

最后,这是编码器处理新测试数据的方式:

print(ohe.transform(x_test).toarray())
>>> [[1. 0. 0. 0. 1.]] # 1 for A1, 0 for A2, 0 for B1, 0 for C1, 1 for C2
Run Code Online (Sandbox Code Playgroud)

编辑

您似乎担心在进行编码后会丢失标签。回到这些实际上很容易,只需将答案包装在数据框中并从ohe.get_feature_names()以下位置指定列名:

pd.DataFrame(ohe.transform(x_test).toarray(), columns = ohe.get_feature_names())
Run Code Online (Sandbox Code Playgroud)