Analyse des données manquantes

Analyse complète du cas

L’analyse complète des cas (ACC), également appelée « suppression des cas par liste », consiste à rejeter les observations lorsque des valeurs de l’une des variables sont manquantes. L’analyse complète des cas consiste à analyser littéralement uniquement les observations pour lesquelles il existe des informations dans toutes les variables de l’ensemble de données.

Quelles variables puis-je imputer avec l’ACC?

L’ACCpeut être appliquée à la fois aux variables catégorielles et numériques.

Hypothèses

L’ACCfonctionne bien lorsque les données sont complètement manquantes au hasard (MCAR). En fait, nous devrions utiliser l’ACCsi nous avons des raisons de croire que les données manquent au hasard, et non pas autrement. Lorsque les données sont MCAR, l’exclusion des observations comportant des informations manquantes revient essentiellement à exclure de manière aléatoire certaines observations de l’ensemble de données. Par conséquent, l’ensemble de données après l’ACC est une représentation équitable de l’ensemble de données original.

Avantages

  • Facile à mettre en œuvre
  • Aucune manipulation de données requise
  • Préserve la distribution des variables (si les données sont MCAR, alors la distribution des variables de l’ensemble de données réduit doit correspondre à la distribution de l’ensemble de données original)

Inconvénients

  • Elle peut exclure une grande partie de l’ensemble de données d’origine (si les données manquantes sont abondantes)
  • Les observations exclues pourraient être instructives pour l’analyse (si les données ne sont pas manquantes au hasard)
  • Le CCA créera un ensemble de données biaisées si les cas complets diffèrent des données originales (par exemple, lorsque les informations manquantes sont en fait MAR ou NMAR et ne manquent pas au hasard).
  • Lors de l’utilisation de nos modèles en production, le modèle ne saura pas comment traiter les données manquantes

Quand utiliser la CCA

  • Les données manquent complètement au hasard
  • Pas plus de 5% de l’ensemble des données contiennent des données manquantes

En pratique, la CCA peut être une méthode acceptable lorsque la quantité d’informations manquantes est faible. Malheureusement, il n’existe pas de règle empirique pour déterminer si la quantité de données manquantes est faible ou négligeable. Toutefois, à titre indicatif, si la quantité totale de données manquantes est égale ou inférieure à ~5% de l’ensemble de données d’origine, la CCA est une option viable.

Dans de nombreux ensembles de données réelles, la quantité de données manquantes n’est jamais faible et, par conséquent, la CCA n’est généralement jamais une option.

La CCA et les modèles en production

Lorsque nous utilisons la CCA, nous supprimons toutes les observations qui contiennent des informations manquantes. Cependant, les données que nous voulons noter avec notre modèle peuvent en effet contenir des informations manquantes. Cela posera un problème lors de l’utilisation de notre modèle dans des systèmes réels, ou comme nous l’appelons, lors de la mise en place ou de la production de modèles : lorsqu’une observation contient des données manquantes, le modèle ne pourra pas la traiter.

Afin d’éviter ce problème, lors de la mise en production des modèles, nous devons faire l’une des deux choses suivantes : soit nous ne notons pas les observations comportant des données manquantes, soit nous remplaçons les valeurs manquantes par un autre nombre.

Dans mon jeu de données, je n’ai presque pas de données manquantes. Quelques part cela est rassurant car cela veut dire que ma base de données est propre. Par contre pour vous montrer un peu ce que l’on peut faire, je vais injecter des valeurs manquantes dans notre fichier d’étude.

 
 
import pandas as pd
import numpy as np

import matplotlib.pyplot as plt


pd.set_option('display.max_columns', None)

data = pd.read_csv('../exportfeature.csv',parse_dates=['date'],infer_datetime_format=True,dayfirst=True,sep=";",encoding='ANSI')

data.head()
# Injectons des données absentes
# 1% dans M2
data.loc[data.sample(frac=0.01).index, 'M2'] = np.nan

# 3% dans M4
data.loc[data.sample(frac=0.01).index, 'M2'] = np.nan

# 5% dans allocation
data.loc[data.sample(frac=0.05).index, 'allocation'] = np.nan

# 15% dans idJockey
data.loc[data.sample(frac=0.15).index, 'idJockey'] = np.nan


# 0.06 % dans Hippodrome
data.loc[data.sample(frac=0.06).index, 'Hippodrome'] = np.nan

# 0.65 % dans nbPartants.1
data.loc[data.sample(frac=0.65).index, 'nbPartants.1'] = np.nan

# On cherche les variables avec des valeurs manquantes

vars_with_na = [var for var in data.columns if data[var].isnull().mean() > 0]
vars_with_na
['M2', 'M4', 'allocation', 'Hippodrome', 'idJockey', 'nbPartants.1', 'iCote']
# On cherche quel est le type des variables manquantes
data[vars_with_na].dtypes
M2               object
M4               object
allocation      float64
Hippodrome       object
idJockey        float64
nbPartants.1    float64
iCote           float64
dtype: object

Il existe des variables numériques et catégorielles pour lesquelles il manque des observations. Nous pouvons voir à partir des types de variables que certaines sont flottantes et d’autres sont des objets.

# On affiche uniquement les variables manquantes

data[vars_with_na].head(10)

M2	M4	allocation	Hippodrome	idJockey	nbPartants.1	iCote
0	3m	3a	90000.0	Vincennes	18.0	17.0	12.0
1	9Da	4a	70000.0	Vincennes	30.0	18.0	12.0
2	Da	1a	44000.0	Vincennes	53.0	NaN	9.0
3	7a	2a	40000.0	Vincennes	143.0	NaN	4.0
4	7a	11a	40000.0	Vincennes	50.0	17.0	8.0
5	6a	0a	22000.0	Vincennes	4.0	NaN	9.0
6	Da	Da	5000.0	Wolvega	19.0	16.0	5.0
7	7a	7a	22000.0	Vincennes	3383.0	16.0	149.0
8	5a	1a	NaN	Vincennes	NaN	18.0	3.0
9	2a	Da	44000.0	Vincennes	1196.0	NaN	55.0
# découvrons le pourcentage d'observations manquantes par variable

# calculer le pourcentage de manquants 
# en utilisant les méthodes isull() et mean() de pandas
data_na = data[vars_with_na].isnull().mean()

# On transfome en dataframe
data_na = pd.DataFrame(data_na.reset_index())

# On rajoute un nom aux colonne pour plus de visibilité
data_na.columns = ['variable', 'na_percentage']

# On ordonne le df
data_na.sort_values(by='na_percentage', ascending=False, inplace=True)
variable	na_percentage
5	nbPartants.1	0.650020
6	iCote	0.180306
4	idJockey	0.150020
3	Hippodrome	0.059988
2	allocation	0.049990
0	M2	0.019801
1	M4	0.004389

La première variable contient beaucoup d’informations manquantes. Nous ne pouvons donc pas utiliser la CCA si nous considérons cette variable, car la plupart des observations de l’ensemble de données seront rejetées.

Pour cette démonstration, je vais ignorer la variable nbPartants.1 et utiliser l’ACC dans le reste de l’ensemble de données.

# variables avec 5% ou mois de na

vars_cca = [var for var in data.columns if data[var].isnull().mean() < 0.05]
vars_cca
['id',
 'place',
 'rapport',
 'date',
 'M1',
 'M2',
 'M3',
 'M4',
 'allocation',
 'nbPartants',
 'idHippodrome',
 'nDistance',
 'nAllocation',
 'idFerrure',
 'rPoids',
 'idOeillere']
# calculer le pourcentage d'observations avec des
# cas : c'est-à-dire avec des valeurs pour toutes les variables

# la méthode dropna(), écarte les observations qui contiennent
# na dans l'une des lignes / colonnes

len(data[vars_cca].dropna()) / len(data)

0.9271361685524776
# supprimer les observations avec na dans toute variable

data_cca = data[vars_cca].dropna()

#Df initial, df après suppression
data.shape, data_cca.shape

((20504, 20), (19010, 16))
# tracer les histogrammes pour toutes les variables numériques

data_cca.hist(bins=50, density=True, figsize=(12, 12))
plt.show()
histo
## vérifions la distribution de quelques variables avant et après 
# cca : histogramme

fig = plt.figure()
ax = fig.add_subplot(111)

# données originelle
data['allocation'].hist(bins=50, ax=ax, density=True, color='red')

# données après cca, l'argument alpha rend la couleur transparente, donc nous pouvons
# voir la superposition des 2 distributions
data_cca['allocation'].hist(bins=50, ax=ax, color='blue', density=True, alpha=0.8)
histo2

On ne distingue rien de spécial.La distribution semble identique.

## vérifions la distribution de quelques variables avant et après 
# cca : diagramme de densité

fig = plt.figure()
ax = fig.add_subplot(111)

# données de départ
data['allocation'].plot.density(color='red')

# après cca
data_cca['allocation'].plot.density(color='blue')
histo3

Comme nous pouvons le voir sur les graphiques ci-dessus, la distribution des variables numériques sélectionnées dans l’ensemble de données du cas original et du cas complet est très similaire, ce que nous attendons de la cca si les données manquent au hasard et seulement pour une petite partie des observations.

Dans les prochaines cellules, je vais étudier la distribution des variables catégorielles. Pour ce faire, j’évaluerai le pourcentage d’observations qui montrent chacune des catégories uniques, comme nous l’avons fait dans les sections 2 et 3 du cours.

# la fonction suivante permet de saisir le pourcentage d'observations
# pour chaque catégorie dans l'ensemble de données original et complet de l'affaire
# et les rassemble dans un nouveau cadre de données


def categorical_distribution(df, df_cca, variable):
    tmp = pd.concat(
        [
            # pourcentage d'observations par catégorie, données originales
            df[variable].value_counts() / len(df),

            # pourcentage d'observations par catégorie, données cca
            df_cca[variable].value_counts() / len(df_cca)
        ],
        axis=1)

    # ajout de titre
    tmp.columns = ['original', 'cca']

    return tmp
    
categorical_distribution(data, data_cca, 'M1')     
	original	cca
1a	0.352468	0.351604
2a	0.152604	0.152236
Da	0.121684	0.122620
3a	0.095494	0.095003
4a	0.063402	0.064072
...	...	...
2Disqa	0.000049	0.000053
8Dista	0.000049	0.000053
Dpga	0.000049	0.000053
4Disqa	0.000049	0.000053
8Dm	0.000049	0.000053
67 rows × 2 columns
categorical_distribution(data, data_cca, 'M2')
	original	cca
1a	0.287017	0.291899
Da	0.144362	0.146660
2a	0.135388	0.138243
3a	0.090616	0.092372
4a	0.064085	0.065807
...	...	...
9Dista	0.000049	0.000053
3Disqa	0.000049	0.000053
8Dpga	0.000049	0.000053
2Dm	0.000049	0.000053
14m	0.000049	0.000053
71 rows × 2 columns

Comme nous pouvons le voir d’après les résultats des cellules ci-dessus, la répartition des étiquettes dans chacune des catégories est très similaire dans l’ensemble de données original et complet du cas, ce qui, là encore, est ce à quoi on s’attend si les données sont complètement manquantes au hasard et si le pourcentage de données manquantes est faible.

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

GCH anime

Je télécharge mon guide gratuit

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

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.