首页 > 解决方案 > sklearn.preprocessing.OneHotEncoder:使用 drop 和 handle_unknown='ignore'

问题描述

我有一些pandas.Series- s,下面 - 我想一次性编码。我通过研究发现,这个'b'级别对于我的预测建模任务并不重要。我可以像这样从我的分析中排除它:

import pandas as pd
from sklearn.preprocessing import OneHotEncoder

s = pd.Series(['a', 'b', 'c']).values.reshape(-1, 1)

enc = OneHotEncoder(drop=['b'], sparse=False, handle_unknown='error')
enc.fit_transform(s)
# array([[1., 0.],
#        [0., 0.],
#        [0., 1.]])
enc.get_feature_names()
# array(['x0_a', 'x0_c'], dtype=object)

但是当我去转换一个新系列时,一个包含两个'b'和一个新级别的系列'd',我收到一个错误:

new_s = pd.Series(['a', 'b', 'c', 'd']).values.reshape(-1, 1)
enc.transform(new_s)

回溯(最后一次调用):文件“”,第 1 行,在文件“/Users/user/Documents/assets/envs/data-science/venv/lib/python3.7/site-packages/sklearn/preprocessing/_encoders .py”,第 390 行,在变换 X_int,X_mask = self._transform(X, handle_unknown=self.handle_unknown) 文件“/Users/user/Documents/assets/envs/data-science/venv/lib/python3.7/ site-packages/sklearn/preprocessing/_encoders.py",第 124 行,在 _transform 中引发 ValueError(msg) ValueError:在转换期间在第 0 列中找到未知类别 ['d']

这是可以预料的,因为我在handle_unknown='error'上面设置了。但是,我想完全忽略除['a', 'c']拟合和后续转换步骤之外的所有类。我试过这个:

enc = OneHotEncoder(drop=['b'], sparse=False, handle_unknown='ignore')
enc.fit_transform(s)
enc.transform(new_s)

回溯(最后一次调用):文件“”,第 1 行,在文件“/Users/user/Documents/assets/envs/data-science/venv/lib/python3.7/site-packages/sklearn/preprocessing/_encoders .py”,第 371 行,在 fit_transform self._validate_keywords() 文件“/Users/user/Documents/assets/envs/data-science/venv/lib/python3.7/site-packages/sklearn/preprocessing/_encoders.py ”,第 289 行,在 _validate_keywords 中,handle_unknown当 drop 参数为“ValueError:handle_unknown必须为 'error' 时,在 _validate_keywords 中”必须为 'error',因为两者都会创建全为零的类别。

scikit-learn 似乎不支持这种模式。有谁知道完成这项任务的 scikit-learn 兼容模式?

标签: pythonmachine-learningscikit-learn

解决方案


看起来sklearn.preprocessing.LabelBinarizer可以适用于这个用例,因为它没有任何参数指定是错误输出还是忽略新类:

>>> import pandas as pd
>>> from sklearn.preprocessing import LabelBinarizer
>>> s = pd.Series(['a', 'b', 'c']).values.reshape(-1, 1)
>>> enc = LabelBinarizer()
>>> enc.fit_transform(s)
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]])
>>> enc.classes_
array(['a', 'b', 'c'], dtype='<U1')
>>> new_s = pd.Series(['a', 'b', 'c', 'd']).values.reshape(-1, 1)
>>> enc.transform(new_s)
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1],
       [0, 0, 0]])

推荐阅读