Statistiques descriptives avec Pandas
Objectif pédagogique : Maîtriser l’analyse exploratoire des données numériques avec les indicateurs de position et de dispersion.
À la fin de ce chapitre, tu seras capable de…
- Calculer les statistiques descriptives fondamentales (moyenne, médiane, quantiles)
- Interpréter les écarts entre moyenne et médiane pour détecter l’asymétrie des distributions
- Analyser la répartition des données à travers les indicateurs de position
- Utiliser la méthode describe() de Pandas pour explorer efficacement un jeu de données
💡 Prérequis : Maîtrise des bases de Pandas (DataFrame, lecture de fichiers CSV, sélection de colonnes)
Mise en contexte
Vous disposez d’un fichier de réservations de véhicules avec des milliers de lignes. Comment rapidement comprendre la structure de vos données ? Découvrez comment une simple différence entre moyenne (4507€) et médiane (1136€) révèle des insights business cruciaux sur votre portefeuille clients. Vous apprendrez à détecter les distributions asymétriques et à interpréter correctement vos indicateurs financiers.
- Importer les packages pandas et numpy
- Charger dans un DataFrame nommé df_reservations les données contenues dans le fichier ‘reservations.csv’ à télécharger ici.
- Afficher les 5 premières lignes de data.
import pandas as pd
import numpy as np
df_reservations = pd.read_csv("reservations.csv")
df_reservations.head()
1 – Statistiques descriptives
- Déterminer les variables numériques et les stocker dans un tableau num_data.
num_data = df_reservations.select_dtypes(include=['int64','float64'])
Il existe certaines statistiques descriptives simples à calculer qui permettent d’obtenir une meilleure compréhension des données quantitatives. C’est ce qu’on appelle les indicateurs de position. Ils sont au nombre de cinq : moyenne, médiane, quantiles, min, max. La moyenne permet de résumer facilement une liste de données numériques en une seule valeur. Elle se calcule avec la formule suivante :

où ![]()
- Calculer la moyenne de chaque variable contenue dans num_data et les stocker dans un DataFrame stats avec comme unique colonne moyenne.
- Comparer la moyenne des montants des location des véhicules (montant_location) avec celle des montants des location avec options (montant_total_avec_options). Que constate-t-on ? Que peut-on dire des moyennes de duree_initiale_jours et de jours_retard ?
Pour la création du DataFrame stats, on pourra utiliser pd.DataFrame et l’attribut columns. Pour le calcul des moyennes, on pourra s’aider de pandas.DataFrame.mean().
stats = pd.DataFrame(num_data.mean(), columns=['moyenne'])
stats.round(2) # Afficher seulement 2 chiffres après la virgule.

- Calculer la médiane de chaque variable contenue dans num_data et ajouter une colonne median à stats.
- Interpréter ces valeurs pour chaque variable en vous servant de la définition donnée précédemment.
stats['median'] = num_data.median()stats
Pour la durée des réservations (duree_initiale_jours), la médiane à 19 jours révèle que la moitié des contrats durent moins de 3 semaines. La moyenne de 73,79 j est fortement tirée vers le haut par une minorité de contrats longue durée. La distribution est très asymétrique à droite ce qui montre que la moyenne est ici trompeuse. Pour le montant de location (hors options), l’écart est énorme. En effet, la médiane à 1 136 € révèle que la moitié des locations coûtent moins de 1 200 €. La moyenne de 4 507 € est gonflée par des contrats longue durée à très fort montant. La moyenne serait un indicateur très biaisé ici.
- Créer une variable mean_med_diff correspondant à la valeur absolue de la différence entre moyenne et médiane.
stats['mean_med_diff'] = abs(stats['moyenne'] - stats['median']) stats.round(2)

Pour donner une interprétation de cette nouvelle variable, il faut bien avoir en tête les ordres de grandeur de chaque variable.
Pour confirmer notre analyse, il est nécessaire de regarder les quantiles de chaque variable.
Les quantiles sont les valeurs qui divisent un jeu de données en intervalles contenant le même nombre de données. De manière générale, on divise le jeu de données en 4 de telle sorte que le premier quantile renvoie la valeur à partir de laquelle on retrouve 25% des valeurs et ainsi de suite pour les autres quantiles.
- Déterminer les quantiles de montant_total_avec_options.
Pour déterminer les quantiles, nous pourrions nous aider de pandas.DataFrame.quantile(q =[0.25,0.5,0.75]).
quant_montant_total_avec_options = num_data[‘montant_total_avec_options’].quantile(q = [0.25, 0.5, 0.75])
quant_montant_total_avec_options

- Ajouter au tableau stats 3 colonnes q1, q2 et q3 renseignant respectivement le premier, deuxième et troisième quantile de chaque variable numérique.
stats[['q1', 'q2', 'q3']] = num_data.quantile(q=[0.25, 0.5, 0.75]).transpose()
stats

- Afficher stats, comparer q2 et q3
- Comparer q3 et la moyenne
- Cela confirme-t-il notre analyse précédente ?
print('q2 < q3 :\n', stats['q2'] < stats['q3'])
print('\nq3 < moyenne :\n', stats['q3'] < stats['moyenne'])


Les résultats montrent que :
- Nous avons q2 < q3 (=True partout), ce qui signifie que nous avons une distribution normale et attendue.
- q3 < moyenne (= False partout). Cela révèle que pour toutes les variables, la moyenne est supérieure au 3ème quartile, ce qui signifie :
- qu’il y a des valeurs extrêmes très élevées
- que la moyenne n’est pas représentative
- qu’il ya nécessité d’utiliser la médiane
- qu’il y a besoin de segmenter l’analyse
On peut compléter notre analyse en s’intéressant au min, max de chaque variable. La différence des deux nous donnera une idée de l’étendue sur laquelle se répartissent les valeurs.
- Ajouter au tableau stats 3 colonnes min, max et min_max_diff renseignant le min, le max et la différence des deux.
- Que remarquez-vous sur la différence des deux ?
💡 À retenir : Les écarts entre min et max sont énormes (facteurs de 100, 1000, voire 3000). Ces grandes étendues sont principalement dues aux valeurs maximales extrêmes. Les données couvrent des cas ultra-variés, du client économique (particuliers) au premium. Il est donc impossible de traiter ces données comme un ensemble homogène. Une segmentation est donc nécessaire.
Deux derniers indicateurs nous permettent d’avoir un bon aperçu : la variance et l’écart-type. Ils font partie de la famille des indicateurs de dispersion :
- La variance, qui mesure la dispersion autour de la moyenne, c’est à dire à quel point les valeurs présentes dans une liste numérique sont écartées de la moyenne. Elle se définit mathématiquement comme suit :

où
est la moyenne, N la longueur de la liste et
les éléments de la liste.
Nous pouvons calculer facilement l’écart type d’une variable en utilisant pandas.Series.std()
- Calculer l’écart type de la variable montant_total_avec_options.
- Afficher l’intervalle moyenne +/- ecart type de la variable montant_total_avec_options.
ecart_type = num_data['montant_total_avec_options'].std()
print("Ecart-type de montant_total_avec_options :", ecart_type)
intervalle = [
float(num_data['montant_total_avec_options'].mean() - ecart_type),
float(num_data['montant_total_avec_options'].mean() + ecart_type)
]
print("Intervalle :", intervalle)
Résultat :
Ecart-type de montant_total_avec_options : 9526.147266190683 Intervalle : [-3809.4040401906823, 15242.890492190683]
- Afficher la médiane et les quartiles de la variables montant_total_avec_options
- Calculer l’intervalle inter-quartile et interpréter les valeurs.
median = float(df_reservations['montant_total_avec_options'].median())
q1 = float(df_reservations['montant_total_avec_options'].quantile(0.25))
q3 = float(df_reservations['montant_total_avec_options'].quantile(0.75))
iqr = float(q3 - q1)
print("Q1 :", np.round(q1, 2))
print("Médiane :", np.round(median, 2))
print("Q3 :", np.round(q3, 2))
print("IQR :", np.round(iqr, 2))
Résultats :
Q1 : 500.84 Médiane : 1388.6 Q3 : 6856.56 IQR : 6355.71
- Ajouter une nouvelle colonne intitulée montant_total_avec_options_in à num_data contenant 1 si la valeur de montant_total_avec_options appartiennent à l’iqr calculé précédemment et 0 sinon.
Pour déterminer les valeurs qui appartiennent à l’intervalle calculé précédemment, on pourra s’aider de pandas.Series.between(int1, int2).astype(int). Pour afficher les proportions on pourra s’aider de pandas.Series.value_counts(normalize = True).
num_data['montant_total_avec_options_in'] = num_data['montant_total_avec_options'].between(q1, q3).astype(int) num_data['montant_total_avec_options_in'].value_counts(normalize = True)

Nous voyons évidemment que 50% des prix de réservations sont dans l’intervalle interquartile (ce résultat est logique et évident).
- Établir les « bornes » au-delà desquelles les prix (montant_total_avec_options) sont considérés comme aberrants.
Les bornes inférieures et supérieures sont calculées par :
borne_inf = Q1 – 1,5IQR
borne_sup = Q3 + 1.5IQR
Toute valeur inférieure à borne_inf ou supérieure à borne_sup est considérée comme valeur aberrante.
Définition des bornes
borne_inf = q1 – 1.5 * iqr
borne_sup = q3 + 1.5 * iqr
Identification des outliers
outliers = num_data[(num_data[‘montant_total_avec_options’] < borne_inf) | (num_data[‘montant_total_avec_options’] > borne_sup)]
print(f »Nombre de valeurs aberrantes : {len(outliers)} »)
💡 À retenir : Nombre de valeurs aberrantes : 587