熊猫类别新级别

时间:2017-08-17 06:23:52

标签: python pandas scikit-learn categorical-data lightgbm

pandas如何分类https://pandas.pydata.org/pandas-docs/stable/categorical.html处理新的和看不见的级别?我正在考虑像scikit-learn like setup。目前,我有类似的东西: https://gist.github.com/geoHeil/5caff5236b4850d673b2c9b0799dc2ce

def: fit() 
  for each column:
   fit a label encoder:
def: transform()
  for each column:
     check if column was unseen
       yes(unseen) replace 
       no: label encode

但这很慢。

显然,像xgboost或lightbm这样的决策树可以直接处理分类数据,即不需要通过这种慢速转换手动操作。 但是看着他们的代码 https://github.com/Microsoft/LightGBM/blob/master/python-package/lightgbm/sklearn.py#L532他们似乎使用LGBMLabelEncoder这是标准的scikit-learn LabelEncoder

我想知道如何处理看不见的数据。

如果需要手动转换,pandas.Categorical允许更快的转换 - 即使新数据中存在看不见的级别?

修改

请参阅https://github.com/geoHeil/pythonQuestions/blob/master/categorical-encoding.ipynb,了解我是如何通过scikit学习常见的嫌疑人工作的。 仍在寻找比我的解决方案更高效的东西。此外,lightGBM https://github.com/Microsoft/LightGBM/issues/789建议使用自定义编码策略。

1 个答案:

答案 0 :(得分:0)

可能有一只大熊猫解决方案,但它最适合使用sklearns LabelBinarizer

from sklearn.preprocessing import LabelBinarizer
df= pd.DataFrame({'A':['a','b','c','a']})
lb = LabelBinarizer()
lb.fit(df["A"])
lb.transform(df["A"])

[[1 0 0]
 [0 1 0]
 [0 0 1]
 [1 0 0]]

df2 = pd.DataFrame({'A':['a','b','d']})
lb.transform(df2['A'])
[[1 0 0]
 [0 1 0]
 [0 0 0]]

所以我们看到'd'基本上既不映射到'a','b'或'c'。 但请注意,有一个bug可能会在下一个sklearn版本中解析。

LabelBinarizer适合在训练期间调用传递给它的值。新值将映射到全零。使用pandas get_dummies编写变换器(如编辑前所示)可能更为可行。

由于列的名称匹配,这可能非常简单。适合第一步并存储列名称,而不仅仅是变换步骤中的变换,而只保留您在拟合中识别的列名称(如果测试集中不存在训练级别,则可能添加zome zero列)。然后你就完成了;)