Comptage ou codage de la fréquence

Dans le codage du comptage, nous remplaçons les catégories par le comptage des observations qui montrent cette catégorie dans l’ensemble de données. De même, nous pouvons remplacer la catégorie par la fréquence – ou le pourcentage – des observations dans l’ensemble de données. C’est-à-dire que si 10 de nos 100 observations montrent la couleur bleue, nous remplacerons le bleu par 10 si nous effectuons le codage du comptage, ou par 0,1 si nous le remplaçons par la fréquence. Ces techniques permettent de saisir la représentation de chaque étiquette dans un ensemble de données, mais le codage ne permet pas nécessairement de prédire le résultat. Il s’agit toutefois de méthodes de codage très populaires dans les concours Kaggle.

L’hypothèse de cette technique est que le nombre d’observations indiqué par chaque variable est quelque peu révélateur du pouvoir prédictif de la catégorie.

Avantages

  • Simple
  • N’élargit pas l’espace de présentation

Inconvénients

  • Si deux catégories différentes apparaissent le même nombre de fois dans l’ensemble de données, c’est-à-dire qu’elles apparaissent dans le même nombre d’observations, elles seront remplacées par le même nombre : elles peuvent perdre des informations précieuses.

Par exemple, s’il y a 10 observations pour la catégorie bleue et 10 observations pour la catégorie rouge, les deux seront remplacées par 10, et donc, après l’encodage, elles apparaîtront comme étant la même chose.

Dans cette démo :

Nous allons voir comment effectuer le comptage ou l’encodage de fréquence avec :

  • Pandas
  • Feature-Engine
import numpy as np
import pandas as pd

# to split the datasets
from sklearn.model_selection import train_test_split

# to encode with feature-engine
from feature_engine.categorical_encoders import CountFrequencyCategoricalEncoder

data = pd.read_csv('../exportfeature.csv',usecols=['place', 'M1', 'M2', 'Hippodrome','idJockey'],sep=";",encoding='ANSI')

data.head()

place	M1	M2	Hippodrome	idJockey
0	1	3a	3m	Vincennes	18
1	1	3a	9Da	Vincennes	30
2	0	1a	Da	Vincennes	53
3	1	Da	7a	Vincennes	143
4	0	1a	7a	Vincennes	50
# examinons le nombre d'étiquettes de chaque variable

for col in data.columns:
    print(col, ': ', len(data[col].unique()), ' labels')
    
place :  2  labels
M1 :  67  labels
M2 :  71  labels
Hippodrome :  199  labels
idJockey :  1943  labels    

Important

Lors de la transformation du comptage des variables catégorielles, il est important de calculer le comptage (ou la fréquence = comptage / total des observations) sur l’ensemble d’entrainement, puis d’utiliser ces nombres pour remplacer les étiquettes dans l’ensemble de test.

data['idJockey'] = data['idJockey'].astype(object)

X_train, X_test, y_train, y_test = train_test_split(
    data[['M1', 'M2', 'Hippodrome','idJockey']], 
    data['place'],  
    test_size=0.3,
    random_state=0)  

X_train.shape, X_test.shape

((14352, 4), (6152, 4))

Comptage et encodage des fréquences avec pandas

# obtenons les comptages pour chacun des labels
# dans la variable Quartier
count_map = X_train['M1'].value_counts().to_dict()

count_map
{'1a': 5015,
 '2a': 2250,
 'Da': 1744,
 '3a': 1415,
 '4a': 904,
 '5a': 642,
 '6a': 514,
 '7a': 362,
 '8a': 306,
 '9a': 258,
 '10a': 190,
 '0a': 122,
 '11a': 102,
 'Dm': 72,
 '12a': 59,
 '13a': 44,
 '1m': 32,
 '2Da': 28,
 '1Da': 25,
 '14a': 24,
 '3Da': 21,
 '3m': 20,
 'Aa': 19,
 '2m': 17,
 '1Dista': 13,
 '4Da': 13,
 '15a': 11,
 '3Dista': 11,
 '4m': 10,
 '5Da': 9,
 '6m': 8,
 '7m': 6,
 '4Dista': 6,
 '2Dista': 6,
 '0m': 6,
 '9m': 6,
 '17a': 4,
 '1Dpga': 4,
 '5Dista': 4,
 '6Da': 4,
 '5m': 4,
 'Dista': 4,
 '1Disqa': 4,
 '2Dpga': 4,
 '7Dista': 3,
 '10m': 3,
 '16a': 2,
 '12m': 2,
 '6Dista': 2,
 '8m': 2,
 '3Dm': 2,
 '11m': 2,
 'Rpa': 2,
 'Am': 1,
 '7Da': 1,
 '10Dista': 1,
 '2Dm': 1,
 '2Disqa': 1,
 'Ta': 1,
 '3Dpga': 1,
 '4Distm': 1,
 '1Dm': 1,
 '8Dista': 1}

Le dictionnaire contient le nombre d’observations par catégorie dans M1.

# remplacer les étiquettes par les chiffres

X_train['M1'] = X_train['M1'].map(count_map)
X_test['M1'] = X_test['M1'].map(count_map)

# Résultat

X_train['M1'].head(10)

2540      642
19008    5015
7624      362
2575     2250
852       514
4855     5015
8154     5015
18928    5015
18286     514
15712     904
Name: M1, dtype: int64
# si au lieu du comptage nous souhaitons la fréquence
# il suffit de diviser le compte par le nombre total d'observations :

frequency_map = (X_train['M1'].value_counts() / len(X_train) ).to_dict()
frequency_map
{5015: 0.3494286510590858,
 2250: 0.15677257525083613,
 1744: 0.12151616499442586,
 1415: 0.09859253065774805,
 904: 0.06298773690078038,
 642: 0.044732441471571904,
 514: 0.03581382385730212,
 362: 0.025222965440356744,
 306: 0.021321070234113712,
 258: 0.01797658862876254,
 190: 0.013238573021181716,
 122: 0.008500557413600892,
 102: 0.007107023411371237,
 72: 0.005016722408026756,
 59: 0.00411092530657748,
 44: 0.0030657748049052395,
 32: 0.002229654403567447,
 4: 0.002229654403567447,
 6: 0.0020903010033444815,
 28: 0.0019509476031215162,
 13: 0.0018115942028985507,
 25: 0.001741917502787068,
 24: 0.0016722408026755853,
 11: 0.0015328874024526198,
 21: 0.001463210702341137,
 20: 0.0013935340022296545,
 19: 0.0013238573021181717,
 17: 0.0011845039018952062,
 2: 0.0009754738015607581,
 1: 0.0006967670011148272,
 10: 0.0006967670011148272,
 9: 0.0006270903010033445,
 8: 0.0005574136008918618,
 3: 0.0004180602006688963}
# remplacer les étiquettes par les fréquences

X_train['M1'] = X_train['M1'].map(frequency_map)
X_test['M1'] = X_test['M1'].map(frequency_map)

Utilisation avec Feature-Engine

data['idJockey'] = data['idJockey'].astype(object)
data['M1'] = data['M1'].astype(object)

X_train, X_test, y_train, y_test = train_test_split(
    data[['M1', 'M2', 'Hippodrome']], 
    data['place'],  
    test_size=0.3,
    random_state=0)  

X_train.shape, X_test.shape
count_enc = CountFrequencyCategoricalEncoder(
    encoding_method='count', # Pour la fréquence ==> encoding_method='frequency'
    variables=['M1', 'M2', 'Hippodrome'])

count_enc.fit(X_train)

CountFrequencyCategoricalEncoder(variables=['M1', 'M2', 'Hippodrome'])

# On retrouve fort heureusement les mêmes valeurs quavec Pandas

count_enc.encoder_dict_
{'M1': {'1a': 5015,
  '2a': 2250,
  'Da': 1744,
  '3a': 1415,
  '4a': 904,
  '5a': 642,
  '6a': 514,
  '7a': 362,
  '8a': 306,
  '9a': 258,
  '10a': 190,
  '0a': 122,
  '11a': 102,
  'Dm': 72,
  '12a': 59,
  '13a': 44,
  '1m': 32,
  '2Da': 28,
  '1Da': 25,
  '14a': 24,
  '3Da': 21,
  '3m': 20,
  'Aa': 19,
  '2m': 17,
  '1Dista': 13,
  '4Da': 13,
  '15a': 11,
  '3Dista': 11,
  '4m': 10,
  '5Da': 9,
  '6m': 8,
  '7m': 6,
  '4Dista': 6,
  '2Dista': 6,
  '0m': 6,
  '9m': 6,
  '17a': 4,
  '1Dpga': 4,
  '5Dista': 4,
  '6Da': 4,
  '5m': 4,
  'Dista': 4,
  '1Disqa': 4,
  '2Dpga': 4,
  '7Dista': 3,
  '10m': 3,
  '16a': 2,
  '12m': 2,
  '6Dista': 2,
  '8m': 2,
  '3Dm': 2,
  '11m': 2,
  'Rpa': 2,
  'Am': 1,
  '7Da': 1,
  '10Dista': 1,
  '2Dm': 1,
  '2Disqa': 1,
  'Ta': 1,
  '3Dpga': 1,
  '4Distm': 1,
  '1Dm': 1,
  '8Dista': 1},
 'M2': {'1a': 4258,
  'Da': 2096,
  '2a': 1966,
  '3a': 1336,
  '4a': 951,
  '5a': 756,
  '6a': 588,
  '7a': 490,
  '8a': 402,
  '9a': 299,
  '10a': 267,
  '0a': 179,
  '11a': 138,
  'Dm': 85,
  '12a': 82,
  '13a': 59,
  '14a': 38,
  '1m': 36,
  '1Da': 30,
  '2Da': 27,
  '3m': 24,
  'Aa': 21,
  '2m': 21,
  '6m': 16,
  '3Da': 16,
  '5m': 14,
  '15a': 12,
  '8m': 11,
  '4Da': 10,
  '4m': 10,
  '6Da': 9,
  '9m': 8,
  'Dista': 7,
  '7m': 7,
  '1Dista': 7,
  '10m': 6,
  '5Dista': 6,
  '3Dista': 6,
  '5Da': 6,
  '2Dista': 5,
  '16a': 4,
  '4Dm': 3,
  '11m': 3,
  'Am': 3,
  '5Dm': 3,
  '2Dpga': 3,
  '4Dista': 2,
  '1Disqa': 2,
  '17a': 2,
  '1Dpga': 2,
  '6Dista': 2,
  'Ta': 2,
  '12m': 2,
  '3Disqa': 1,
  '3Distm': 1,
  '8Da': 1,
  '0m': 1,
  '7Da': 1,
  'Dpga': 1,
  '13m': 1,
  '14m': 1,
  '9Da': 1,
  '8Dm': 1,
  '8Dista': 1,
  '12Dist.a': 1,
  '1Dm': 1,
  '2Dm': 1},
 'Hippodrome': {'Vincennes': 2712,
  'Cagnes-sur-Mer': 773,
  'Enghien': 669,
  'Mons': 661,
  'Avenches': 500,
  'Cabourg': 440,
  'Vichy': 427,
  'Laval': 385,
  'Caen': 369,
  'Mauquenchy': 340,
  'Wolvega': 325,
  'Toulouse': 323,
  'Marseille-Vivaux': 273,
  'La Capelle': 223,
  'Graignes': 219,
  'Reims': 213,
  'Le Croisé-Laroche': 203,
  'Amiens': 181,
  'Agen': 178,
  'Beaumont-de-Lomagne': 177,
  'Lyon-La Soie': 176,
  'Marseille-Borély': 173,
  'Hyères': 172,
  'Saint-Galmier': 168,
  'Pornichet': 167,
  'Nantes': 154,
  'Chartres': 154,
  'Feurs': 149,
  'Lyon-Parilly': 143,
  'Bordeaux  Le Bouscat': 141,
  'Meslay-du-Maine': 135,
  'Les Sables-d&#039Olonne': 129,
  'Argentan': 128,
  'Angers': 118,
  'Le Mont-Saint-Michel': 90,
  'Chatelaillon-La Rochelle': 89,
  'Cherbourg': 87,
  'Lisieux': 86,
  'Le Mans': 84,
  'Saint-Malo': 81,
  'Châteaubriant': 80,
  'Cavaillon': 77,
  'Vire': 76,
  'Pontchâteau': 74,
  'Cordemais': 73,
  'Solvalla': 72,
  'Divonne-les-Bains': 63,
  'Aby': 61,
  'Strasbourg': 52,
  'Maure-de-Bretagne': 52,
  'Saint-Brieuc': 51,
  'Nancy': 46,
  'Langon-Libourne': 45,
  'Bjerke': 44,
  'Cagnes': 42,
  'Jägersro': 37,
  'Craon': 36,
  'Kuurne': 36,
  'Tongres': 35,
  'Gelsenkirchen': 35,
  'Bergsaker': 33,
  'Son Pardo  Majorque': 31,
  'Farjestad': 30,
  'Cholet': 29,
  'Eskilstuna': 29,
  'Axevalla': 27,
  'Salon-de-Provence': 25,
  'Marseille': 22,
  'Halmstad': 22,
  'Ostersund': 22,
  'Duindigt': 21,
  'Waregem': 20,
  'Hagmyren': 18,
  'Rambouillet': 16,
  'Umaker': 16,
  'Orebro': 16,
  'Jarlsberg': 16,
  'Gavle': 16,
  'Munich-Daglfing': 15,
  'Lyon': 13,
  'Clairefontaine': 13,
  'Mantorp': 13,
  'Romme': 13,
  'Royan-la Palmyre': 12,
  'Bordeaux': 12,
  'Boden': 11,
  'Rattvik': 11,
  'Straubing': 11,
  'Bréhal': 11,
  'Dannero': 10,
  'Bernay': 10,
  'Alençon': 10,
  'Bollnas': 10,
  'Saint': 10,
  'Lignières': 10,
  'Ecommoy': 10,
  'Montier-en-Der': 10,
  'Leangen': 9,
  'Melton': 9,
  'Sablé-sur-Sarthe': 9,
  'Berlin-Mariendorf': 9,
  'Le Croisé': 9,
  'Aalborg': 8,
  'Singapour': 8,
  'Vaggeryd': 8,
  'Arras': 8,
  'Bergen': 8,
  'Carentan': 8,
  'Arjang': 8,
  'Oraison': 8,
  'Aix-les-Bains': 8,
  'La Roche-Posay': 8,
  'L&#039Isle-sur-La Sorgue': 7,
  'Castera-Verduzan': 7,
  'Segré': 7,
  'Le Touquet': 7,
  'Skelleftea': 6,
  'Angoulême': 6,
  'Montauban': 6,
  'Dieppe': 6,
  'Biarritz': 6,
  'Paray-le-Monial': 6,
  'Frauenfeld': 6,
  'Marsa': 6,
  'Vannes': 6,
  'Nîmes': 6,
  'Vitré': 6,
  'Castillonnès': 6,
  'Auch': 6,
  'Montluçon-Néris-les-Bains': 6,
  'Villeneuve-sur-Lot': 6,
  'Agon-Coutainville': 5,
  'La Gacilly': 5,
  'Odense': 5,
  'Niort': 5,
  'Avignon': 5,
  'Saint-Jean-de-Monts': 5,
  'Chatillon-sur-Chalaronne': 5,
  'Kalmar': 5,
  'Villeréal': 5,
  'Son Pardo': 5,
  'Saint-Omer': 4,
  'Forus': 4,
  'Biri': 4,
  'Hambourg Bahrenfeld': 4,
  'Grenade-sur-Garonne': 4,
  'Fougères': 4,
  'Carpentras': 4,
  'Tours-Chambray': 4,
  'Zonza': 4,
  'Vermo': 4,
  'Vittel': 4,
  'Maure': 4,
  'Beaumont': 4,
  'Challans': 4,
  'Skive': 4,
  'Harstad': 4,
  'Ajaccio': 3,
  'Baden': 3,
  'Amal': 3,
  'Dundalk': 3,
  'Momarken': 3,
  'Visby': 3,
  'Erbray': 3,
  'Prunelli-di-Fiumorbo': 3,
  'Landivisiau': 3,
  'Eauze': 3,
  'Nort-sur-Erdre': 2,
  'Ebreichsdorf (Magna Racino)': 2,
  'Meslay': 2,
  'Machecoul': 2,
  'Vienne Krieau': 2,
  'Charlottenlund': 2,
  'Ostende': 2,
  'Meadowlands': 2,
  'Kouvola': 2,
  'Laon': 2,
  'Mikkeli': 2,
  'Geelong': 1,
  'La Roche': 1,
  'Chatillon': 1,
  'Saint-Moritz': 1,
  '(Q+ du mardi 25': 1,
  '(R1C5) lundi 14': 1,
  'Dinslaken': 1,
  'Hambourg Horn': 1,
  'Chatelaillon': 1,
  'Tours': 1,
  '(R1C1)  Vendredi 04': 1,
  'Loudéac': 1,
  'Montluçon': 1,
  'Ballarat': 1,
  'Yonkers-New York': 1,
  'lundi 02': 1,
  'Dielsdorf': 1}}
X_train = count_enc.transform(X_train)
X_test = count_enc.transform(X_test)

# Explorons le résultat
X_train.head()
	M1	M2	Hippodrome
2540	642	756	440
19008	5015	1336	80
7624	362	2096	2712
2575	2250	179	440
852	514	756	178

**Note

Si la variable argument est laissée à None, le codeur identifiera automatiquement toutes les variables catégorielles.

Le codeur ne codera pas les variables numériques. Donc, si certaines de vos variables numériques sont en fait des catégories, vous devrez les reformuler en tant qu’objet avant d’utiliser le codeur.

Notez que s’il y a une variable dans le jeu de test, pour laquelle l’encodeur n’a pas de numéro à attribuer (la catégorie n’a pas été vue dans le jeu de train), l’encodeur retournera une erreur.

Entrée [ ]:
 
GCH anime

Je télécharge mon guide gratuit

Vous recevrez votre guide par email sans aucun engagement de votre part.

Si vous voulez découvrir comment fonctionne la librairie pandas ou bien l’environnement Jupyter, n’hésitez pas à consulter les cours ci-dessous.

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.