J'essaie d'utiliser la variable LabelEncoder
de scikit-learn pour coder un pandas DataFrame
d'étiquettes de chaîne. Étant donné que la structure de données comporte de nombreuses colonnes (plus de 50), je souhaite éviter de créer un objet LabelEncoder
pour chaque colonne; Je préférerais simplement avoir un seul gros objet LabelEncoder
qui fonctionne dans tout mes colonnes de données.
Le fait de placer DataFrame
entier dans LabelEncoder
crée l'erreur ci-dessous. Veuillez garder à l'esprit que j'utilise des données factices ici; En réalité, je traite avec environ 50 colonnes de données étiquetées sous forme de chaîne. Il faut donc une solution qui ne référence aucune colonne par son nom.
import pandas
from sklearn import preprocessing
df = pandas.DataFrame({
'pets': ['cat', 'dog', 'cat', 'monkey', 'dog', 'dog'],
'owner': ['Champ', 'Ron', 'Brick', 'Champ', 'Veronica', 'Ron'],
'location': ['San_Diego', 'New_York', 'New_York', 'San_Diego', 'San_Diego',
'New_York']
})
le = preprocessing.LabelEncoder()
le.fit(df)
Traceback (dernier appel passé): Fichier "", ligne 1, dans Fichier "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/preprocessing/label.py", ligne 103, bien adapté y = column_or_1d (y, warn = True) Fichier "/Users/bbalin/anaconda/lib/python2.7/site-packages/sklearn/utils/validation.py", ligne 306, dans column_or_1d raise ValueError ("forme d'entrée incorrecte {0}". format (forme)) ValueError: mauvaise forme d'entrée (6, 3)
Des idées sur la façon de contourner ce problème?
Vous pouvez facilement le faire si,
df.apply(LabelEncoder().fit_transform)
MODIFIER:
Cette réponse datant de plus d'un an et ayant généré de nombreux votes positifs (y compris une prime), je devrais probablement étendre cela davantage.
Pour inverse_transform et transform, vous devez faire un peu de piratage.
from collections import defaultdict
d = defaultdict(LabelEncoder)
Avec cela, vous conservez maintenant toutes les colonnes LabelEncoder
en tant que dictionnaire.
# Encoding the variable
fit = df.apply(lambda x: d[x.name].fit_transform(x))
# Inverse the encoded
fit.apply(lambda x: d[x.name].inverse_transform(x))
# Using the dictionary to label future data
df.apply(lambda x: d[x.name].transform(x))
Comme mentionné par larsmans, LabelEncoder () ne prend comme argument qu'un tableau à une seule fois . Cela dit, il est assez facile de lancer votre propre encodeur d'étiquettes qui fonctionne sur plusieurs colonnes de votre choix et renvoie une image transformée. Mon code ici est basé en partie sur l'excellent article de blog de Zac Stewart trouvé ici .
La création d'un encodeur personnalisé implique simplement la création d'une classe qui répond aux méthodes fit()
, transform()
et fit_transform()
. Dans votre cas, un bon début pourrait être quelque chose comme ceci:
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import Pipeline
# Create some toy data in a Pandas dataframe
fruit_data = pd.DataFrame({
'fruit': ['Apple','orange','pear','orange'],
'color': ['red','orange','green','green'],
'weight': [5,6,3,4]
})
class MultiColumnLabelEncoder:
def __init__(self,columns = None):
self.columns = columns # array of column names to encode
def fit(self,X,y=None):
return self # not relevant here
def transform(self,X):
'''
Transforms columns of X specified in self.columns using
LabelEncoder(). If no columns specified, transforms all
columns in X.
'''
output = X.copy()
if self.columns is not None:
for col in self.columns:
output[col] = LabelEncoder().fit_transform(output[col])
else:
for colname,col in output.iteritems():
output[colname] = LabelEncoder().fit_transform(col)
return output
def fit_transform(self,X,y=None):
return self.fit(X,y).transform(X)
Supposons que nous voulions encoder nos deux attributs catégoriques (fruit
et color
), tout en laissant l'attribut numérique weight
seul. Nous pourrions faire ceci comme suit:
MultiColumnLabelEncoder(columns = ['fruit','color']).fit_transform(fruit_data)
Ce qui transforme notre ensemble de données fruit_data
à partir de
à
Si vous transmettez une trame de données composée entièrement de variables catégorielles et omettez le paramètre columns
, chaque colonne sera codée (ce qui, je crois, correspond à ce que vous recherchiez à l'origine):
MultiColumnLabelEncoder().fit_transform(fruit_data.drop('weight',axis=1))
Cela transforme
à
.
Notez que cela va probablement s’étouffer lorsqu’il essaiera de coder des attributs déjà numériques (ajoutez du code pour gérer cela si vous le souhaitez).
Une autre caractéristique intéressante de cette fonction est que nous pouvons utiliser ce transformateur personnalisé dans un pipeline:
encoding_pipeline = Pipeline([
('encoding',MultiColumnLabelEncoder(columns=['fruit','color']))
# add more pipeline steps as needed
])
encoding_pipeline.fit_transform(fruit_data)
Nous n'avons pas besoin d'un LabelEncoder.
Vous pouvez convertir les colonnes en catégories, puis obtenir leurs codes. J'ai utilisé un dictionnaire de compréhension ci-dessous pour appliquer ce processus à chaque colonne et pour envelopper le résultat dans une trame de données de même forme avec des index et des noms de colonne identiques.
>>> pd.DataFrame({col: df[col].astype('category').cat.codes for col in df}, index=df.index)
location owner pets
0 1 1 0
1 0 2 1
2 0 0 0
3 1 1 2
4 1 3 1
5 0 2 1
Pour créer un dictionnaire de cartographie, vous pouvez simplement énumérer les catégories à l'aide d'une compréhension du dictionnaire:
>>> {col: {n: cat for n, cat in enumerate(df[col].astype('category').cat.categories)}
for col in df}
{'location': {0: 'New_York', 1: 'San_Diego'},
'owner': {0: 'Brick', 1: 'Champ', 2: 'Ron', 3: 'Veronica'},
'pets': {0: 'cat', 1: 'dog', 2: 'monkey'}}
cela ne répond pas directement à votre question (pour laquelle Naputipulu Jon et PriceHardman ont des réponses fantastiques)
Cependant, pour quelques tâches de classification, etc., vous pouvez utiliser
pandas.get_dummies(input_df)
cela peut entrer dataframe avec des données catégorielles et renvoyer une dataframe avec des valeurs binaires. les valeurs de variables sont codées dans les noms de colonne dans la base de données résultante. plus
Cela fait un an et demi après les faits, mais moi aussi, je devais être capable de .transform()
plusieurs colonnes du cadre de données du pandas à la fois (et de pouvoir aussi .inverse_transform()
). Ceci développe l'excellente suggestion de @PriceHardman ci-dessus:
class MultiColumnLabelEncoder(LabelEncoder):
"""
Wraps sklearn LabelEncoder functionality for use on multiple columns of a
pandas dataframe.
"""
def __init__(self, columns=None):
self.columns = columns
def fit(self, dframe):
"""
Fit label encoder to pandas columns.
Access individual column classes via indexig `self.all_classes_`
Access individual column encoders via indexing
`self.all_encoders_`
"""
# if columns are provided, iterate through and get `classes_`
if self.columns is not None:
# ndarray to hold LabelEncoder().classes_ for each
# column; should match the shape of specified `columns`
self.all_classes_ = np.ndarray(shape=self.columns.shape,
dtype=object)
self.all_encoders_ = np.ndarray(shape=self.columns.shape,
dtype=object)
for idx, column in enumerate(self.columns):
# fit LabelEncoder to get `classes_` for the column
le = LabelEncoder()
le.fit(dframe.loc[:, column].values)
# append the `classes_` to our ndarray container
self.all_classes_[idx] = (column,
np.array(le.classes_.tolist(),
dtype=object))
# append this column's encoder
self.all_encoders_[idx] = le
else:
# no columns specified; assume all are to be encoded
self.columns = dframe.iloc[:, :].columns
self.all_classes_ = np.ndarray(shape=self.columns.shape,
dtype=object)
for idx, column in enumerate(self.columns):
le = LabelEncoder()
le.fit(dframe.loc[:, column].values)
self.all_classes_[idx] = (column,
np.array(le.classes_.tolist(),
dtype=object))
self.all_encoders_[idx] = le
return self
def fit_transform(self, dframe):
"""
Fit label encoder and return encoded labels.
Access individual column classes via indexing
`self.all_classes_`
Access individual column encoders via indexing
`self.all_encoders_`
Access individual column encoded labels via indexing
`self.all_labels_`
"""
# if columns are provided, iterate through and get `classes_`
if self.columns is not None:
# ndarray to hold LabelEncoder().classes_ for each
# column; should match the shape of specified `columns`
self.all_classes_ = np.ndarray(shape=self.columns.shape,
dtype=object)
self.all_encoders_ = np.ndarray(shape=self.columns.shape,
dtype=object)
self.all_labels_ = np.ndarray(shape=self.columns.shape,
dtype=object)
for idx, column in enumerate(self.columns):
# instantiate LabelEncoder
le = LabelEncoder()
# fit and transform labels in the column
dframe.loc[:, column] =\
le.fit_transform(dframe.loc[:, column].values)
# append the `classes_` to our ndarray container
self.all_classes_[idx] = (column,
np.array(le.classes_.tolist(),
dtype=object))
self.all_encoders_[idx] = le
self.all_labels_[idx] = le
else:
# no columns specified; assume all are to be encoded
self.columns = dframe.iloc[:, :].columns
self.all_classes_ = np.ndarray(shape=self.columns.shape,
dtype=object)
for idx, column in enumerate(self.columns):
le = LabelEncoder()
dframe.loc[:, column] = le.fit_transform(
dframe.loc[:, column].values)
self.all_classes_[idx] = (column,
np.array(le.classes_.tolist(),
dtype=object))
self.all_encoders_[idx] = le
return dframe
def transform(self, dframe):
"""
Transform labels to normalized encoding.
"""
if self.columns is not None:
for idx, column in enumerate(self.columns):
dframe.loc[:, column] = self.all_encoders_[
idx].transform(dframe.loc[:, column].values)
else:
self.columns = dframe.iloc[:, :].columns
for idx, column in enumerate(self.columns):
dframe.loc[:, column] = self.all_encoders_[idx]\
.transform(dframe.loc[:, column].values)
return dframe.loc[:, self.columns].values
def inverse_transform(self, dframe):
"""
Transform labels back to original encoding.
"""
if self.columns is not None:
for idx, column in enumerate(self.columns):
dframe.loc[:, column] = self.all_encoders_[idx]\
.inverse_transform(dframe.loc[:, column].values)
else:
self.columns = dframe.iloc[:, :].columns
for idx, column in enumerate(self.columns):
dframe.loc[:, column] = self.all_encoders_[idx]\
.inverse_transform(dframe.loc[:, column].values)
return dframe
Exemple:
Si df
et df_copy()
sont des types de données pandas
de type mixte, vous pouvez appliquer le MultiColumnLabelEncoder()
aux colonnes dtype=object
de la manière suivante:
# get `object` columns
df_object_columns = df.iloc[:, :].select_dtypes(include=['object']).columns
df_copy_object_columns = df_copy.iloc[:, :].select_dtypes(include=['object'].columns
# instantiate `MultiColumnLabelEncoder`
mcle = MultiColumnLabelEncoder(columns=object_columns)
# fit to `df` data
mcle.fit(df)
# transform the `df` data
mcle.transform(df)
# returns output like below
array([[1, 0, 0, ..., 1, 1, 0],
[0, 5, 1, ..., 1, 1, 2],
[1, 1, 1, ..., 1, 1, 2],
...,
[3, 5, 1, ..., 1, 1, 2],
# transform `df_copy` data
mcle.transform(df_copy)
# returns output like below (assuming the respective columns
# of `df_copy` contain the same unique values as that particular
# column in `df`
array([[1, 0, 0, ..., 1, 1, 0],
[0, 5, 1, ..., 1, 1, 2],
[1, 1, 1, ..., 1, 1, 2],
...,
[3, 5, 1, ..., 1, 1, 2],
# inverse `df` data
mcle.inverse_transform(df)
# outputs data like below
array([['August', 'Friday', '2013', ..., 'N', 'N', 'CA'],
['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
['August', 'Monday', '2014', ..., 'N', 'N', 'NJ'],
...,
['February', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
['March', 'Tuesday', '2013', ..., 'N', 'N', 'NJ']], dtype=object)
# inverse `df_copy` data
mcle.inverse_transform(df_copy)
# outputs data like below
array([['August', 'Friday', '2013', ..., 'N', 'N', 'CA'],
['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
['August', 'Monday', '2014', ..., 'N', 'N', 'NJ'],
...,
['February', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
['April', 'Tuesday', '2014', ..., 'N', 'N', 'NJ'],
['March', 'Tuesday', '2013', ..., 'N', 'N', 'NJ']], dtype=object)
Vous pouvez accéder à des classes de colonne, des étiquettes de colonne et des encodeurs de colonne individuels permettant d'adapter chaque colonne via l'indexation:
mcle.all_classes_
mcle.all_encoders_
mcle.all_labels_
En supposant que vous essayiez simplement d'obtenir un objet sklearn.preprocessing.LabelEncoder()
pouvant être utilisé pour représenter vos colonnes, tout ce que vous avez à faire est:
le.fit(df.columns)
Dans le code ci-dessus, vous aurez un numéro unique correspondant à chaque colonne . Plus précisément, vous aurez une correspondance 1: 1 de df.columns
à le.transform(df.columns.get_values())
. Pour obtenir le codage d'une colonne, il suffit de le transmettre à le.transform(...)
. Par exemple, ce qui suit va obtenir le codage pour chaque colonne:
le.transform(df.columns.get_values())
En supposant que vous souhaitiez créer un objet sklearn.preprocessing.LabelEncoder()
pour toutes vos étiquettes de ligne, vous pouvez effectuer les opérations suivantes:
le.fit([y for x in df.get_values() for y in x])
Dans ce cas, vous avez probablement des étiquettes de lignes non uniques (comme le montre votre question). Pour voir les classes créées par l'encodeur, vous pouvez effectuer le.classes_
. Vous noterez que cela devrait avoir les mêmes éléments que dans set(y for x in df.get_values() for y in x)
. Une fois encore, pour convertir une étiquette de ligne en une étiquette codée, utilisez le.transform(...)
. Par exemple, si vous souhaitez récupérer le libellé de la première colonne du tableau df.columns
et de la première ligne, procédez comme suit:
le.transform([df.get_value(0, df.columns[0])])
La question que vous avez posée dans votre commentaire est un peu plus compliquée, mais peut encore.
le.fit([str(z) for z in set((x[0], y) for x in df.iteritems() for y in x[1])])
Le code ci-dessus fait ce qui suit:
LabelEncoder
ne prenant pas en charge les n-uplets en tant que nom de classe.LabelEncoder
.Maintenant, utiliser ce nouveau modèle est un peu plus compliqué. En supposant que nous voulions extraire la représentation du même élément que celui que nous avons recherché dans l'exemple précédent (la première colonne de df.columns et la première ligne), nous pouvons procéder ainsi:
le.transform([str((df.columns[0], df.get_value(0, df.columns[0])))])
Rappelez-vous que chaque recherche est maintenant une représentation sous forme de chaîne d'un tuple contenant Le (colonne, ligne).
Depuis scikit-learn 0.20, vous pouvez utiliser sklearn.compose.ColumnTransformer
et sklearn.preprocessing.OneHotEncoder
:
Si vous n’avez que des variables catégorielles, OneHotEncoder
directement:
from sklearn.preprocessing import OneHotEncoder
OneHotEncoder(handle_unknown='ignore').fit_transform(df)
Si vous avez des fonctionnalités de type hétérogène:
from sklearn.compose import make_column_transformer
from sklearn.preprocessing import RobustScaler
from sklearn.preprocessing import OneHotEncoder
categorical_columns = ['pets', 'owner', 'location']
numerical_columns = ['age', 'weigth', 'height']
column_trans = make_column_transformer(
(categorical_columns, OneHotEncoder(handle_unknown='ignore'),
(numerical_columns, RobustScaler())
column_trans.fit_transform(df)
Plus d'options dans la documentation: http://scikit-learn.org/stable/modules/compose.html#columntransformer-for-heterogen-data
Non, LabelEncoder
ne le fait pas. Il prend des tableaux 1-D d'étiquettes de classe et produit des tableaux 1-D. Il est conçu pour gérer les étiquettes de classe dans les problèmes de classification, et non les données arbitraires. Toute tentative de le forcer dans d'autres utilisations nécessitera du code pour transformer le problème actuel en problème qu'il résout (et la solution pour revenir à l'espace d'origine).
Suite aux commentaires soulevés sur la solution de @PriceHardman Je proposerais la version suivante de la classe:
class LabelEncodingColoumns(BaseEstimator, TransformerMixin):
def __init__(self, cols=None):
pdu._is_cols_input_valid(cols)
self.cols = cols
self.les = {col: LabelEncoder() for col in cols}
self._is_fitted = False
def transform(self, df, **transform_params):
"""
Scaling ``cols`` of ``df`` using the fitting
Parameters
----------
df : DataFrame
DataFrame to be preprocessed
"""
if not self._is_fitted:
raise NotFittedError("Fitting was not preformed")
pdu._is_cols_subset_of_df_cols(self.cols, df)
df = df.copy()
label_enc_dict = {}
for col in self.cols:
label_enc_dict[col] = self.les[col].transform(df[col])
labelenc_cols = pd.DataFrame(label_enc_dict,
# The index of the resulting DataFrame should be assigned and
# equal to the one of the original DataFrame. Otherwise, upon
# concatenation NaNs will be introduced.
index=df.index
)
for col in self.cols:
df[col] = labelenc_cols[col]
return df
def fit(self, df, y=None, **fit_params):
"""
Fitting the preprocessing
Parameters
----------
df : DataFrame
Data to use for fitting.
In many cases, should be ``X_train``.
"""
pdu._is_cols_subset_of_df_cols(self.cols, df)
for col in self.cols:
self.les[col].fit(df[col])
self._is_fitted = True
return self
Cette classe adapte l'encodeur au kit d'apprentissage et utilise la version ajustée lors de la transformation. La version initiale du code peut être trouvée ici .
si nous avons une seule colonne pour faire le codage d'étiquette et son inverse transformer sa facile comment le faire quand il y a plusieurs colonnes en python
def stringtocategory(dataset):
'''
@author puja.sharma
@see The function label encodes the object type columns and gives label encoded and inverse tranform of the label encoded data
@param dataset dataframe on whoes column the label encoding has to be done
@return label encoded and inverse tranform of the label encoded data.
'''
data_original = dataset[:]
data_tranformed = dataset[:]
for y in dataset.columns:
#check the dtype of the column object type contains strings or chars
if (dataset[y].dtype == object):
print("The string type features are : " + y)
le = preprocessing.LabelEncoder()
le.fit(dataset[y].unique())
#label encoded data
data_tranformed[y] = le.transform(dataset[y])
#inverse label transform data
data_original[y] = le.inverse_transform(data_tranformed[y])
return data_tranformed,data_original
J'ai vérifié le code source ( https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/preprocessing/label.py ) de LabelEncoder. Il était basé sur un ensemble de transformations numpy, dont np.unique (). Et cette fonction prend seulement une entrée de tableau 1-d. (Corrigez-moi si je me trompe).
Very Rough ideas ... Identifiez d’abord les colonnes qui ont besoin de LabelEncoder, puis parcourez chaque colonne en boucle.
def cat_var(df):
"""Identify categorical features.
Parameters
----------
df: original df after missing operations
Returns
-------
cat_var_df: summary df with col index and col name for all categorical vars
"""
col_type = df.dtypes
col_names = list(df)
cat_var_index = [i for i, x in enumerate(col_type) if x=='object']
cat_var_name = [x for i, x in enumerate(col_names) if i in cat_var_index]
cat_var_df = pd.DataFrame({'cat_ind': cat_var_index,
'cat_name': cat_var_name})
return cat_var_df
from sklearn.preprocessing import LabelEncoder
def column_encoder(df, cat_var_list):
"""Encoding categorical feature in the dataframe
Parameters
----------
df: input dataframe
cat_var_list: categorical feature index and name, from cat_var function
Return
------
df: new dataframe where categorical features are encoded
label_list: classes_ attribute for all encoded features
"""
label_list = []
cat_var_df = cat_var(df)
cat_list = cat_var_df.loc[:, 'cat_name']
for index, cat_feature in enumerate(cat_list):
le = LabelEncoder()
le.fit(df.loc[:, cat_feature])
label_list.append(list(le.classes_))
df.loc[:, cat_feature] = le.transform(df.loc[:, cat_feature])
return df, label_list
Le retourné df serait celui après l'encodage, et label_list vous montrera ce que toutes ces valeurs signifient dans la colonne correspondante. Ceci est un extrait d’un script de traitement de données que j’ai écrit pour le travail. Faites-moi savoir si vous pensez qu'il pourrait y avoir d'autres améliorations.
EDIT: Je veux juste mentionner ici que les méthodes ci-dessus fonctionnent avec des trames de données sans manquer le meilleur. Vous ne savez pas comment cela fonctionne pour que le cadre de données contienne des données manquantes (J'ai eu un accord avec la procédure manquante avant d'exécuter les méthodes ci-dessus)
Si vous avez les deux types de données numériques et catégoriques dans le cadre de données Vous pouvez utiliser: ici, X est mon cadre de données ayant les deux variables numériques et catégoriques.
from sklearn import preprocessing
le = preprocessing.LabelEncoder()
for i in range(0,X.shape[1]):
if X.dtypes[i]=='object':
X[X.columns[i]] = le.fit_transform(X[X.columns[i]])
Remarque: cette technique est utile si vous ne souhaitez pas les reconvertir.
import pandas as pd
from sklearn.preprocessing import LabelEncoder
train=pd.read_csv('.../train.csv')
#X=train.loc[:,['waterpoint_type_group','status','waterpoint_type','source_class']].values
# Create a label encoder object
def MultiLabelEncoder(columnlist,dataframe):
for i in columnlist:
labelencoder_X=LabelEncoder()
dataframe[i]=labelencoder_X.fit_transform(dataframe[i])
columnlist=['waterpoint_type_group','status','waterpoint_type','source_class','source_type']
MultiLabelEncoder(columnlist,train)
Ici, je lis un csv d’emplacement et, en fonction, je passe la liste des colonnes que je veux étiqueter et le cadre de données que je veux appliquer.
Principalement utilisé @Alexander answer mais dû faire quelques changements -
cols_need_mapped = ['col1', 'col2']
mapper = {col: {cat: n for n, cat in enumerate(df[col].astype('category').cat.categories)}
for col in df[cols_need_mapped]}
for c in cols_need_mapped :
df[c] = df[c].map(mapper[c])
Ensuite, pour réutiliser ultérieurement, vous pouvez simplement enregistrer la sortie dans un document json. Lorsque vous en aurez besoin, vous pourrez la lire et utiliser la fonction .map()
comme je l’ai fait ci-dessus.
Il est possible de faire tout cela directement dans les pandas et convient parfaitement à une capacité unique de la méthode replace
.
Commençons par créer un dictionnaire de dictionnaires associant les colonnes et leurs valeurs à leurs nouvelles valeurs de remplacement.
transform_dict = {}
for col in df.columns:
cats = pd.Categorical(df[col]).categories
d = {}
for i, cat in enumerate(cats):
d[cat] = i
transform_dict[col] = d
transform_dict
{'location': {'New_York': 0, 'San_Diego': 1},
'owner': {'Brick': 0, 'Champ': 1, 'Ron': 2, 'Veronica': 3},
'pets': {'cat': 0, 'dog': 1, 'monkey': 2}}
Comme il s'agira toujours d'un mappage un à un, nous pouvons inverser le dictionnaire interne pour obtenir un mappage des nouvelles valeurs sur l'original.
inverse_transform_dict = {}
for col, d in transform_dict.items():
inverse_transform_dict[col] = {v:k for k, v in d.items()}
inverse_transform_dict
{'location': {0: 'New_York', 1: 'San_Diego'},
'owner': {0: 'Brick', 1: 'Champ', 2: 'Ron', 3: 'Veronica'},
'pets': {0: 'cat', 1: 'dog', 2: 'monkey'}}
Maintenant, nous pouvons utiliser la capacité unique de la méthode replace
pour prendre une liste imbriquée de dictionnaires et utiliser les clés externes comme colonnes et les clés internes comme valeurs à remplacer.
df.replace(transform_dict)
location owner pets
0 1 1 0
1 0 2 1
2 0 0 0
3 1 1 2
4 1 3 1
5 0 2 1
Nous pouvons facilement revenir à l'original en reliant à nouveau la méthode replace
df.replace(transform_dict).replace(inverse_transform_dict)
location owner pets
0 San_Diego Champ cat
1 New_York Ron dog
2 New_York Brick cat
3 San_Diego Champ monkey
4 San_Diego Veronica dog
5 New_York Ron dog
Après beaucoup de recherches et d’expérimentation de réponses ici et ailleurs, je pense que votre réponse est ici :
pd.DataFrame (colonnes = df.colonnes, data = LabelEncoder (). fit_transform (df.values.flatten ()). reshape (df.shape))
Cela préservera les noms de catégorie dans les colonnes:
import pandas as pd
from sklearn.preprocessing import LabelEncoder
df = pd.DataFrame([['A','B','C','D','E','F','G','I','K','H'],
['A','E','H','F','G','I','K','','',''],
['A','C','I','F','H','G','','','','']],
columns=['A1', 'A2', 'A3','A4', 'A5', 'A6', 'A7', 'A8', 'A9', 'A10'])
pd.DataFrame(columns=df.columns, data=LabelEncoder().fit_transform(df.values.flatten()).reshape(df.shape))
A1 A2 A3 A4 A5 A6 A7 A8 A9 A10
0 1 2 3 4 5 6 7 9 10 8
1 1 5 8 6 7 9 10 0 0 0
2 1 3 9 6 8 7 0 0 0 0
Un chemin court pour LabelEncoder()
plusieurs colonnes avec un dict()
:
from sklearn.preprocessing import LabelEncoder
le_dict = {col: LabelEncoder() for col in columns }
for col in columns:
le_dict[col].fit_transform(df[col])
et vous pouvez utiliser ce le_dict
pour labelEncode toute autre colonne:
le_dict[col].transform(df_another[col])
Le problème est la forme des données (pd dataframe) que vous transmettez à la fonction fit . Vous devez passer 1d list.