2017-08-17 3 views
1

Comment pandas catégorique https://pandas.pydata.org/pandas-docs/stable/categorical.html gérer des niveaux nouveaux et invisibles? Je pense à une installation de type scikit-learn. À l'heure actuelle, j'ai quelque chose comme: https://gist.github.com/geoHeil/5caff5236b4850d673b2c9b0799dc2cepandas catégories nouveaux niveaux

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 

mais cela est assez lent. Apparemment, les arbres de décision comme xgboost ou lightbm peuvent directement gérer des données catégorielles, c'est-à-dire que l'on n'aurait pas besoin de manipuler manuellement cette conversion lente. Mais en regardant leur code https://github.com/Microsoft/LightGBM/blob/master/python-package/lightgbm/sklearn.py#L532 ils semblent utiliser LGBMLabelEncoder qui est un standard scikit-learn LabelEncoder.

Je me demande comment cela peut gérer les données non-vues.

Si une conversion manuelle est nécessaire serait pandas.Categorical permettre une conversion plus rapide - même si les niveaux inédits sont dans les nouvelles données?

modifier

S'il vous plaît voir https://github.com/geoHeil/pythonQuestions/blob/master/categorical-encoding.ipynb pour un aperçu que je ne pouvais pas travailler scikit-learn suspects habituels de. Toujours à la recherche de quelque chose de plus performant que ma solution. Aussi lightGBM https://github.com/Microsoft/LightGBM/issues/789 suggère d'utiliser une stratégie de codage personnalisée.

+1

Pandas.Categorical suffit de les remplir avec Nan. Scikit-apprendre également ne pas gérer de nouvelles données, ils seront probablement retirés ou remplacés par Nan. Essayez d'utiliser LabelEncoder avec des données invisibles et vous obtiendrez 'ValueError: y contient de nouvelles étiquettes:'. –

+0

pourquoi cette question est downvoted ?? Je suppose qu'un petit ensemble de données reproductible et un peu désiré pourraient aider à mieux comprendre le problème ... – MaxU

+2

@MaxU Peut-être parce qu'à mon avis c'est plus un problème d'approche algorithmique qu'un problème de programmation. C'est un problème fréquent dans l'apprentissage automatique sur la façon de gérer les données invisibles et [Cross-validated] (http://stats.stackexchange.com) est le bon endroit pour cela. –

Répondre

0

Il pourrait y avoir un solutin de pandas géants, mais il fonctionne probablement mieux avec 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]] 

Nous voyons donc que 'd' est essentiellement mis en correspondance ni 'a', 'b' ou 'c'. Notez cependant qu'il existe un bug qui sera probablement résolu dans l'une des prochaines versions de sklearn. Le LabelBinarizer est adapté pendant l'entraînement et rappelle les valeurs qui lui ont été transmises. Les nouvelles valeurs sont mappées à tous les zéros. Il serait peut-être plus faisable d'écrire un transformateur (comme vu ici avant l'édition) en utilisant les pandas get_dummies.

Cela pourrait être assez simple en raison de la correspondance des noms des colonnes. Ajuster dans la première étape et stocker les noms de colonnes, juste transformer dans le processus de transformation, mais ne conserver que les noms de colonnes que vous avez identifiés dans l'ajustement (en ajoutant éventuellement des colonnes zéro zome si les niveaux d'entraînement ne sont pas présents). Alors vous avez terminé;)

+0

Mais il manque le focabulary - vous ne garantissez pas qu'un second df avec des niveaux catégoriques potentiellement invisibles ou des niveaux dans différents ordres à encoder correctement. –

+0

Vous avez raison, le manque d'ordre peut être manquant, cependant, lorsque vous travaillez sur des colonnes avec des valeurs discrètes, de nouvelles catégories/valeurs seront mappées à zéro dans chaque colonne. – Quickbeam2k1

+0

En ce qui concerne la commande, si df_1 contient a, b et que ceci est mappé à 1,2 et que df_2 contient b, c cela devrait être mappé à 2,0 donc ça ne devrait pas poser de problème? Ou est-ce que je me méprends? –