Statistiques avec Python : Guide pratique
Statistiques avec Python : Guide pratique
Christophe Chesneau
Christophe Chesneau
[Link]
1 Introduction 7
1.1 Spyder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
1.2 Premiers pas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.3 Tableau de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.4 Manipulations d’un tableau de données . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
1.5 Importation de données . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2 Lois de probabilité 17
2.1 Loi normale . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.1.1 Densité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.1.2 Fonction de répartition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.1.3 Fonction de quantile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.1.4 Generation de valeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.1.5 Mesures de moments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.1.6 Complements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.2 Loi de Poisson . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.2.1 Probabilité de masse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.2.2 Fonction de répartition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.2.3 Fonction de quantile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.2.4 Generation de valeurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.2.5 Mesures de moments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.2.6 Complements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4 Statistique descriptive 35
4.1 Description de caractères quantitatifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.2 Description de caractères qualitatifs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.3 Description conjointe de caractères quantitatifs . . . . . . . . . . . . . . . . . . . . . . 40
4.4 Description conjointe de caractères qualitatifs . . . . . . . . . . . . . . . . . . . . . . . 41
4.5 Description conjointe d’un caractère quantitatif et d’un caractère qualitatif . . . . . . . 43
4.6 Description conjointe de deux caractères quantitatifs et d’un caractère qualitatif . . . . 45
5 Tests statistiques 47
5.1 Test de la normalité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.2 Test d’une moyenne . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
C. Chesneau 3
Table des matières
∼ Note ∼
Ce document propose une introduction à l’analyse de données avec le logiciel Python.
[Link]@[Link]
Bonne lecture !
C. Chesneau 4
1 Introduction
1 Introduction
1.1 Spyder
Avant toute chose, on recommande d’installer la distribution Python appelée Anaconda disponible
ici :
[Link]
Il est conseillé de travailler avec l’interface Spyder. Vous allez avoir un espace de travail qui se
présente de la manière suivante :
Dans la grande fenêtre de gauche, on tape les codes, comme un fichier texte quelconque. On les exécute
en sélectionnant les lignes nécessaires, puis en tapant F9. Les résultats numériques s’affichent dans la
fenêtre en bas à droite. Si graphique il y a, on peut le visualiser en haut à droite, ainsi que toutes les
variables définies, et autres.
Pour commencer, dans la fenêtre de saisie, on importe certains outils appelés modules qui vont
nous permettre de faire des statistiques et des graphiques. Ainsi, dans la fenêtre de saisie, on écrit :
C. Chesneau 7
1 Introduction
import numpy as np
import pylab
import pandas as pd
import seaborn as sns
import statistics
import [Link] as smi
puis on exécute ces commandes (avec F9 après les avoir toutes sélectionnées, ou en appuyant plusieurs
fois sur F9, ou autre). On les importe une fois pour toute dans tout le document. De brèves
présentations de ces modules sont données ci-dessous :
— matplotlib est un module offrant une bibliothèque complète pour créer des visualisations sta-
tiques, animées et interactives.
— scipy est un module offrant un grand nombre de lois de probabilité, et d’outils statistiques.
— numpy est un module offrant des fonctions mathématiques complètes, des générateurs de nombres
aléatoires, et diverses routines d’algèbre linéaire.
— pylab est un module permettant d’utiliser de manière aisée les modules NumPy et matplotlib.
— pandas est un module offrant des structures de données adaptées à l’analyse statistique et
des fonctions facilitant l’accès aux données, l’organisation des données et la manipulation des
données.
— seaborn est un module offrant une interface de haut niveau et concise pour l’obtention de
graphiques statistiques informatifs et attractifs.
— statistics est un module offrant des fonctions pour calculer des statistiques mathématiques
de données numériques (à valeur réelle).
— statsmodels est un module offrant des classes et des fonctions pour l’estimation de divers
modèles statistiques, pour les tests statistiques et pour l’exploration des données.
Pour une description détaillée de ces modules, on peut faire, par exemple : help(scipy)
C. Chesneau 8
1 Introduction
virgule permet de mettre plusieurs opérations côte à côte. Une commande équivalente à 5 **
3 est pow(5, 3).
— On fait :
a, b, c = 3, 5, 7
Dès lors, cela revient à affecter à a la valeur 3, à b la valeur 5, et à c la valeur 7.
— Ensuite, on fait :
a / b, a - b / c, (a - b) / c
Cela renvoie : (0.6, 2.2857142857142856, -0.2857142857142857)
— On fait :
print("la valeur de", a, "+", b, "est :", a + b)
Cela renvoie : la valeur de 3 + 5 est : 8
— On fait :
[Link]([a, b, c])
Cela renvoie : array([3, 5, 7]). Ainsi, on a créé le vecteur numérique (a, b, c), correspondant
à (3, 5, 7).
— On fait :
[Link](c + b - a) == 3
Cela renvoie : True. Ainsi, on a appelé la fonction “racine carrée” dans numpy (abregé en np) pour
√
finalement demander si 9 est égale à 3, d’où le True. En fait, les opérateurs de comparaisons
disponibles dans Python sont : == qui signifie “ égal à”, != qui signifie “différent de”, > qui
signifie “strictement supérieur à”, >= qui signifie “supérieur ou égal à”, < qui signifie “strictement
inférieur à” et ‘<= qui signifie “inférieur ou égal à”.
— On fait :
type([Link](c + b)), type("test")
Cela renvoie : (numpy.float64, str). Ainsi, la commande type nous permet de savoir de quel
type est l’objet considéré. Ici, float64 signifie que c’est un nombre réel et str que c’est du
texte.
— On fait :
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = [list1, list2]
List3
Cela renvoie : [[1, 2, 3], [4, 5, 6]]. On a ainsi créé une liste de valeurs, constituée de
deux sous-listes.
— On fait :
list1[0] + list3[1][0]
Cela renvoie : 5. Ainsi, on a cherché le premier élément de list1 (Python commençant à l’indice
0, contrairement à R notamment), donc 1, et le premier élément de la deuxième sous-liste de
C. Chesneau 9
1 Introduction
C. Chesneau 10
1 Introduction
polynome(3.5)
Cela renvoie : 6.25. On a ainsi créé une fonction polynome qui correspond à p(x) = x2 − 2x + 1,
et demandé la valeur de celui-ci en x = 3.5. On peut créer un large panel de fonctions avec
cette syntaxe. Attention, l’indentation est importante ; Il doit y avoir un décalage dans les lignes
écrites dans le corps de la fonction, sinon elles ne seront pas prises en compte dans l’exécution.
— On fait :
i = 0
while i < 3 :
print("OK j’ai compris")
i = i + 1
Cela renvoie :
OK j’ai compris
OK j’ai compris
OK j’ai compris
Ainsi, on a créé une boucle “tant que”, et plus précisément : “tant qu’une condition n’est pas véri-
fiée, faire cela”. Attention, tout comme la définition d’une fonction, l’indentation est importante
pour tous les types de boucles.
— On fait :
i = 0
for i in range(0, 3) :
print("OK j’ai encore compris")
i = i + 1
Cela renvoie :
OK j’ai encore compris
OK j’ai encore compris
OK j’ai encore compris
Ainsi, on a créé une boucle “pour”, et plus précisément : “pour un indice allant de tant à tant,
faire cela”.
— On fait :
a = 2
if a > 5 :
print("OK c’est clair")
else :
print("OK c’est très clair")
Cela renvoie :
OK c’est très clair
C. Chesneau 11
1 Introduction
Ainsi, on a créé une boucle “si”, et plus précisément : “si une condition est vérifiée, faire cela,
sinon, faire autre chose”.
Pour allez plus loin, voir les fonctions map, filter, lambda, apply, etc.
En fait, il y aurait encore beaucoup à faire pour tester toutes les commandes intéressantes de
Python, mais les opérations ci-dessus suffisent pour notre objectif d’analyse statistique, sachant que
d’autres nouvelles commandes seront présentées au fil du document.
Ainsi,
— t définit un vecteur contenant les valeurs 0, 0.1, 0.2, . . . , 9.8, 9.9. Il y a donc 100 valeurs (chiffre
que l’on peut retrouver en faisant [Link](t)).
— t est un vecteur contenant les valeurs de sin(t) pour les valeurs de t, donc sin(0), sin(0.1),
sin(0.2), . . . , sin(9.8), sin(9.9).
— y est un vecteur à 100 composantes, dont chacune des composantes contient une des modalités
choisies au hasard parmi "A", "B" et "C".
— dataset est le tableau de données constitué des colonnes t appelée Time, x appelé x et y appelé
y.
En toute circonstance, dans un premier temps, on peut demander une entête de dataset en faisant :
[Link]()
Cela renvoie :
Time x y
0 0.0 0.000000 C
1 0.1 0.099833 C
2 0.2 0.198669 A
3 0.3 0.295520 C
4 0.4 0.389418 C
C. Chesneau 12
1 Introduction
Si l’on ne dispose pas des informations sur la nature des données, on peut faire :
[Link]()
Cela renvoie :
<class ’[Link]’>
RangeIndex: 100 entries, 0 to 99
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Time 100 non-null float64
1 x 100 non-null float64
2 y 100 non-null object
dtypes: float64(2), object(1)
memory usage: 2.5+ KB
Ainsi, il y a 100 lignes et 3 colonnes, float64 précise que les données associées sont numériques, et
object précise que les données associées sont non-numériques (caractères, etc.).
La suite de cette section concerne la manipulation du jeu de données dataset.
C. Chesneau 13
1 Introduction
C. Chesneau 14
1 Introduction
C. Chesneau 15
2 Lois de probabilité
2 Lois de probabilité
Cette section montre comment on peut manipuler les lois de probabilité avec Python.
2.1.1 Densité
La densité de la loi normale centrée réduite, notée N (0, 1), est donnée par
1 x2
f (x) = √ e− 2 , x ∈ R.
2π
def normal_distribution_function(x) :
value = [Link](x)
return value
C. Chesneau 17
2 Lois de probabilité
x_min = -4
x_max = 4
y = [Link](x)
[Link]()
[Link](x_min,x_max)
[Link](0,0.45)
[Link]("x")
Cela renvoie :
Plus généralement, la densité de la loi normale (pas forcément centrée, ni réduite), notée N (µ, σ 2 ),
est donnée par
1 1 x−µ 2
f (x; µ, σ) = √ e− 2 ( σ ) , x ∈ R.
σ 2π
La commande associée est [Link](x, mu, sigma).
Par exemple, pour calculer sa valeur en x = 0, avec µ = 1 et σ = 2, on fait :
[Link](0, 1, 2)
C. Chesneau 18
2 Lois de probabilité
x_min = -5
x_max = 7
y = [Link](x, 1, 2)
[Link]()
[Link](x_min,x_max)
[Link](0,0.22)
[Link]("x")
Cela renvoie :
La fonction de répartition de la loi normale centrée réduite N (0, 1) est donnée par
Z x Z t
1 t2
Φ(x) = f (t)dt = √ e− 2 dt, x ∈ R.
−∞ 2π −∞
C. Chesneau 19
2 Lois de probabilité
Elle n’a pas de forme analytique simple. La commande associée est [Link](x).
Le terme “cdf” en anglais désigne “cumulative distribution function”, ce qui équivaut à la “fonction
de répartition” en français.
Par exemple, pour calculer sa valeur en x = 0, on fait :
[Link](0)
x_min = -3
x_max = 3
y = [Link](x)
[Link]()
[Link](x_min,x_max)
[Link](0,1)
[Link]("x")
Cela renvoie :
C. Chesneau 20
2 Lois de probabilité
Plus généralement, la fonction de répartition de la loi normale N (µ, σ 2 ), est donnée par
Z x Z x
1 1 t−µ 2
Φ(x; µ, σ) = f (t; µ, σ)dt = √ e− 2 ( σ ) dt, x ∈ R.
−∞ σ 2π −∞
[Link](0, 1, 2)
x_min = -5
x_max = 7
y = [Link](x, 1, 2)
[Link]()
[Link](x_min,x_max)
[Link](0,1)
[Link]("x")
Cela renvoie :
C. Chesneau 21
2 Lois de probabilité
Elle n’a pas d’expression analytique simple. La commande associée est [Link](x, mu, sigma).
Le terme “ppf” en anglais désigne “percent point function”, ce qui équivaut à la “fonction de quantile”
en français.
Elle permet, entre autres, de calculer les quartiles de la loi normale. Pour la loi normale centrée
réduite, on fait :
[Link]([0.25, 0.5, 0.75])
Partant d’une variable aléatoire X suivant la loi normale N (µ, σ 2 ), on est en mesure de générer
des données pouvant être des observations de celle-ci.
La commande associée est : [Link](size = nombredevaleurs, loc = mu, scale = sigma).
Le terme “rvs” en anglais désigne “random values”, pour valeurs aléatoires.
Ainsi, par exemple, pour générer 100 valeurs d’une variable aléatoire X suivant la loi N (0, 1), on
fait :
[Link](size = 100)
C. Chesneau 22
2 Lois de probabilité
Cela renvoie :
A chaque expérience, on aura d’autres valeurs dues au caractère aléatoire du processus de génération.
Un autre, pour générer 100 valeurs d’une variable aléatoire X suivant la loi N (1, 4), on fait :
Cela renvoie :
C. Chesneau 23
2 Lois de probabilité
Pour une visualisation de telles valeurs, on peut utiliser un histogramme. Par exemple, à partir de
10000 valeurs générées à partir d’une variable aléatoire X suivant la loi normale N (1, 4), on peut faire :
[Link](x, range = (-4, 5), bins = 20, color = "yellow", edgecolor = "orange")
[Link]("x")
[Link]("Histogramme de 10000 valeurs générées avec une loi N(1,4)")
Cela renvoie :
Soit X un variable aléatoire suivant la loi normale N (µ, σ 2 ). Alors on sait que son espérance,
variance et écart-type sont
E(X) = µ, V(X) = σ 2 , σ(X) = σ,
C. Chesneau 24
2 Lois de probabilité
respectivement. Partant de valeurs précise pour µ et σ, on peut retrouver ces valeurs avec les com-
mandes : [Link](loc = mu, scale = sigma), [Link](loc = mu, scale = sigma)
et [Link](loc = mu, scale = sigma), respectivement. Le terme “mean” désigne “moyenne”,
le terme “var” désigne “variance” et le terme “std” désigne “standard deviation”.
Dans le cadre d’une loi normale, ces commandes sont inutiles. Toutefois, elles se transposent à
d’autres lois de probabilité dont l’espérance, variance et écart-type reposent sur des formules moins
immédiates. Il faut donc les connaître à toute fin utile.
Ainsi, par exemple, on fait :
[Link](loc = 1, scale = 2)
def x_normal_distribution_function(x) :
value = x * [Link](x, loc = 1, scale = 2)
return value
[Link](loc = 1, scale = 2)
def v_normal_distribution_function(x) :
value = (x - 1)**2 * [Link](x, loc = 1, scale = 2)
return value
C. Chesneau 25
2 Lois de probabilité
2.1.6 Complements
— On peut définir une loi de probabilité en amont pour simplifier les commandes à venir en faisant,
par exemple :
dist = [Link](loc = 1, scale = 3)
Dès lors, on définit la loi normale N (1, 9). On peut manipuler ces caractéristiques avec des
commandes du type : [Link](0), [Link]([0, 3, 6]), [Link](size = 1000), etc.
— La plupart des lois à densité usuelles sont disponibles dans Python. Les principales sont :
— [Link](a, b) : Loi uniforme dans l’intervalle [a, b],
— stats.t(m) : loi de Student à m degrés de liberté,
— [Link](a, b) : loi beta de paramètres a et b,
— stats.chi2(m) : loi du chi2 à m degrés de liberté,
— [Link](scale = 1 / v) : loi exponentielle de paramètre v, i.e., de densité f (x; v) =
ve−vx , x ≥ 0.
— [Link](a, scale = 1 / v) : loi gamma de paramètres a et v, i.e., de densité f (x; a, v) =
(v a /Γ(a))xa−1 e−vx , x ≥ 0.
La probabilité de masse de la loi de Poisson de paramètre λ, notée P(λ), est donnée par
λx
p(x; λ) = e−λ , x ∈ N.
x!
C. Chesneau 26
2 Lois de probabilité
[Link]([0, 3, 5, 9], 2)
Cela renvoie : array([0.13533528, 0.18044704, 0.03608941, 0.00019095])
Donc, par analogie, on a par exemple : p(5; 2) = 0.03608941.
On veut vérifier que la somme des valeurs de p(x; λ) pour x ∈ N, avec λ = 2 par exemple, fait bien
1, avec les commandes suivantes :
a = [Link](list(range(100)), 2)
[Link](a)
Cela renvoie : 1.0
On a choisi la limite de 99 car, au-delà, les valeurs de la probabilité de masse est extrêmement
petite ; une série infinie étant difficilement prise en compte par Python.
On peut tracer le graphique en bâton de p(x; λ), avec λ = 2 par exemple, en faisant :
x = list(range(10))
height = [Link](x, 2)
width = 0.2
[Link](0,0.3)
[Link]()
C. Chesneau 27
2 Lois de probabilité
[x]
X
F (x; λ) = p(t; λ), x ∈ R,
t=0
x = list(range(9))
cdf = [Link](x,2)
Cela renvoie :
Dans le cadre d’une loi de Poisson, la fonction de quantile est définie par
C. Chesneau 28
2 Lois de probabilité
Cette définition peut s’adapter à toute loi discrète. Elle n’a pas d’expression analytique simple. La
commande associée est [Link](x, lambda).
Elle permet, entre autres, de calculer les quartiles de la loi de Poisson. Pour λ = 2, on fait :
[Link]([0.25, 0.5, 0.75], 2)
Cela renvoie : array([1., 2., 3.]). Ainsi, le premier quartile vaut 1, le deuxième correspondant à
la médiane vaut 2, et le troisième vaut 3.
Partant d’une variable aléatoire X suivant la loi de Poisson P(λ), on est en mesure de générer des
données pouvant être des observations de celle-ci.
La commande associée est : [Link](lambda, size = nombredevaleurs).
Ainsi, par exemple, pour générer 100 valeurs d’une variable aléatoire X suivant la loi P(2), on fait :
[Link](2, size = 100)
Cela renvoie :
array([2, 1, 0, 4, 1, 3, 3, 2, 4, 2, 3, 1, 3, 1, 0, 3, 4, 3, 5, 1, 4, 1,
1, 1, 3, 4, 5, 2, 3, 0, 2, 0, 3, 1, 5, 1, 2, 1, 1, 1, 1, 1, 4, 1,
3, 3, 3, 2, 1, 1, 0, 1, 1, 1, 0, 3, 1, 5, 1, 2, 3, 2, 4, 0, 3, 1,
3, 1, 1, 1, 2, 5, 4, 1, 3, 0, 1, 0, 2, 1, 0, 1, 1, 2, 1, 1, 1, 3,
1, 3, 3, 4, 2, 3, 2, 1, 1, 2, 2, 1])
A chaque expérience, on aura d’autres valeurs dues au caractère aléatoire du processus de génération.
Pour une visualisation de telles valeurs, on peut utiliser un histogramme. Par exemple, à partir de
10000 valeurs générées d’une variable aléatoire X suivant la loi normale N (1, 4), on peut faire :
[Link](x, range = (0, 9), bins = 40, color = "magenta", edgecolor = "orange")
[Link]("x")
[Link]("Histogramme de 10000 valeurs générées avec une loi P(2)")
Cela renvoie :
C. Chesneau 29
2 Lois de probabilité
Soit X un variable aléatoire suivant la loi de Poisson P(2). Alors on sait que son espérance, variance
et écart-type sont
√
E(X) = λ, V(X) = λ, σ(X) = λ,
respectivement. Partant de valeurs précises pour λ, on peut retrouver ces valeurs avec les commandes :
[Link](lambda), [Link](lambda) et [Link](lambda), res-
pectivement.
Dans le cadre d’une loi de Poisson, tout comme la loi normale, ces commandes sont inutiles. Toute-
fois, elles se transposent à d’autres lois de probabilité dont l’espérance, variance et écart-type reposent
sur des formules moins immédiates. Il faut donc les connaître à toute fin utile.
Ainsi, par exemple, on fait :
[Link](3)
x = list(range(100))
a = x * [Link](x, 3)
[Link](a)
[Link](3)
C. Chesneau 30
2 Lois de probabilité
2.2.6 Complements
— On peut définir une loi de probabilité en amont pour simplifier les commandes à venir en faisant,
par exemple :
dist = [Link](3)
Dès lors, on définit la loi de Poisson P(3). On peut manipuler ces caractéristiques avec des
commandes du type : [Link](0), [Link]([0, 3, 6]), [Link](size = 1000), etc.
— La plupart des lois discrètes usuelles sont disponibles dans Python. Les principales sont :
— [Link](p) : loi de Bernoulli de paramètre p,
— [Link](n, p) : loi binomiale de paramètres n et p,
— [Link](n, p) : loi binomiale négative de paramètres n et p,
— [Link](p) : loi géométrique de paramètre p,
— [Link](M, n, N) : loi hypergéometrique de paramètres n, p et N .
C. Chesneau 31
3 Données de référence : tips
Il s’agit désormais de voir des commandes Python permettant d’analyser des données de toutes
sortes. Pour ce faire, nous allons procéder avec un exemple concret : dans le reste de ce document (hors
exercices), on considère le jeu de données intitulé tips. Il est disponible ici :
[Link]
Dans un premier temps, on présente ce jeu de données. Un serveur a enregistré des informations
sur chaque pourboire qu’il a reçu sur une période de quelques mois de travail dans un restaurant. Il a
collecté plusieurs variables qui sont :
— total_bill (facture) en dollars : caractère quantitatif,
— tip (pourboire) en dollars : caractère quantitatif,
— sex (sexe) de celui qui a payé la facture : caractère qualitatif de modalités : Male et Female
— smoker (fumeur) indique s’il y avait des fumeurs dans la soirée : caractère qualitatif de moda-
lités : Yes and No
— day (jour) de la semaine : caractère qualitatif de modalités : Sun, Sat, Fri, et Thur,
— time (moment) de la journée : caractère qualitatif de modalités : Lunch et Dinner,
— size (taille) de la table : caractère quantitatif discret.
En tout, le serveur a enregistré 244 pourboires. Les données ont été rapportées dans une collection
d’études de cas pour les statistiques d’entreprises. La référence de ce jeu de données est :
Bryant, P. G. and Smith, M (1995) Practical Data Analysis : Case Studies in Business Statistics.
Homewood, IL : Richard D. Irwin Publishing.
L’intérêt majeur du jeu de données tips est qu’il contient toutes les natures des caractères possibles,
avec des liens existants entre eux (sans valeurs manquantes, ou autres “problèmes”). Il est donc parfait
pour une première analyse.
On rappelle que l’on suppose charger tous les modules nécessaires, à savoir :
tips = pd.read_csv("[Link]
header = 0, sep = ",")
C. Chesneau 33
3 Données de référence : tips
[Link]()
Cela renvoie :
On retrouve les noms de nos caractères, avec un aperçu rapide des données saisies.
Également, on peut avoir une description rapide du jeu de données en faisant :
[Link]()
Cela renvoie :
<class ’[Link]’>
RangeIndex: 244 entries, 0 to 243
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 total_bill 244 non-null float64
1 tip 244 non-null float64
2 sex 244 non-null object
3 smoker 244 non-null object
4 day 244 non-null object
5 time 244 non-null object
6 size 244 non-null int64
dtypes: float64(2), int64(1), object(4)
memory usage: 13.5+ KB
On retrouve les informations dont on disposait déjà (nombre de données par caractère, nature des
caractères, etc.)
Le reste du document concerne l’analyse de ces données. Pour ce faire, il est supposé que les notions
suivantes sont connues un minimum : outils de statistiques descriptives, graphiques statistiques, tests
statistiques et intervalles de confiance.
C. Chesneau 34
4 Statistique descriptive
4 Statistique descriptive
Cette partie s’intéresse à la statistique descriptive des données de tips en prenant en compte la
nature des caractères.
Cela renvoie :
On a donc les moyennes, écart-types, minimums, premier quartiles, deuxième quartiles (médianes),
troisième quartiles, et maximums des trois caractères.
On aurait pu faire une analyse locale des variables. Par exemple, avec la variable total_bill, on
aurait pu faire :
tips.total_bill.describe()
Cela renvoie :
count 244.000000
mean 19.785943
std 8.902412
min 3.070000
25% 13.347500
50% 17.795000
75% 24.127500
max 50.810000
Name: total_bill, dtype: float64
C. Chesneau 35
4 Statistique descriptive
Ou bien : tips["total_bill"].describe().
Les composantes de cette sortie s’obtiennent en faisant :
tips.total_bill.mean(), tips.total_bill.std(), tips.total_bill.min(),
tips.total_bill.max(), tips.total_bill.median() et
tips.total_bill.quantile([0.25, 0.5, 0.75]).
[Link](bins = 20)
Cela renvoie :
[Link]()
Cela renvoie :
On peut bien sûr faire une analyse graphique locale. Si on considère le caractère total_bill, on peut
afficher son histogramme en faisant :
C. Chesneau 36
4 Statistique descriptive
tips.total_bill.hist(bins = 20)
Cela renvoie :
On peut alors dire que la forme de l’histogramme est non-symétrique, ce qui présage une non-normalité
des données. On approfondira ce point par la suite, avec le test de Shapiro-Wilk.
Pour avoir sa version normalisée, on fait :
Ou bien, pour avoir le même en plus joli et avec la densité estimée d’affichée, on fait :
[Link](tips.total_bill)
[Link](column = "total_bill")
Cela renvoie :
C. Chesneau 37
4 Statistique descriptive
On constate plusieurs points dépassant la moustache supérieure, traduisant la présence de points que
l’on peut considérer comme “anormaux” (ou extrêmes) par rapport aux autres. Cela va encore dans le
sens d’une non-normalité des données.
Éventuellement, on peut afficher un graphique qui mélange histogramme et boîte à moustaches ; le
graphique en violon. Pour ce faire, on fait :
Cela renvoie :
On y trouve une boîte à moustaches, et une figure symétrique par rapport à l’axe des ordonnées, donc
chaque côté indique une estimation de la densité de l’histogramme (dont de la forme de l’histogramme).
L’analyse précédente peut se faire identiquement avec les caractères tip et size.
Cela renvoie :
[Link]([Link], "freq")
Cela renvoie :
C. Chesneau 38
4 Statistique descriptive
col_0 freq
sex
Female 87
Male 157
On peut représenter les données de sex avec un diagramme en barres (ou bâtons) ou un diagramme
circulaire.
Pour le diagramme en barres, on fait :
t = [Link]([Link], "freq")
[Link]()
Cela renvoie :
On peut faire de même avec les fréquences au lieu des effectifs, en faisant :
t = [Link]([Link], "freq")
[Link](subplots=True, figsize = (3, 3))
C. Chesneau 39
4 Statistique descriptive
Cela renvoie :
Cela renvoie :
C. Chesneau 40
4 Statistique descriptive
tips.total_bill.corr([Link])
Cela renvoie : 0.6757341092113641. Comme celui-ci appartient à l’intervalle [0.5, 0.75], on peut ef-
fectivement parler de lien linéaire modéré. Cela sera affiné par la suite avec le test de corrélation de
Pearson.
Pour une version graphique évoluée de cette analyse, on fait :
Cela renvoie :
On dispose alors des histogrammes des données de chaque caractère, ainsi qu’une estimation de leur
densité (forme), le nuage de points, et une droite l’ajustant “du mieux possible”. La zone ombragée
correspond à une zone de confiance dans laquelle la droite peut évoluer tout en gardant un ajustement
correct (c’est une “zone de confiance”).
C. Chesneau 41
4 Statistique descriptive
smoker No Yes
sex
Female 54 33
Male 97 60
Partant de ces effectifs, on pourra faire un test exact de Fisher ou du Chi-deux pour étudier un lien
possible entre ces caractères.
Cela peut se représenter avec un diagramme en barres. On fait :
t = [Link]([Link], [Link])
[Link]()
Cela renvoie :
Cela renvoie :
C. Chesneau 42
4 Statistique descriptive
On peut également comparer les diagrammes circulaires mis côte à côte en faisant :
t = [Link]([Link], [Link])
[Link](subplots = True, figsize = (12, 6))
Cela renvoie :
On constate que, à caractère quantitatifs fixé, les moyennes différent plus ou moins sensiblement en
fonctions des modalités de sex.
Si on se focalise sur total_bill, on peut avoir une analyse descriptive plus détaillée en faisant :
Cela renvoie :
C. Chesneau 43
4 Statistique descriptive
En termes graphique, on peut comparer l’allure des deux histogrammes associées aux deux modalités
de sex en faisant :
Cela renvoie :
Également, on peut visualiser la différence des moyennes avec le graphique des moyennes. On fait :
Cela renvoie :
Les points représentent les moyennes de total_bill pour les modalités de sex. Les traits représentent
des intervalles de confiance de ces moyennes.
On peut également comparer graphiquement les médianes en faisant :
C. Chesneau 44
4 Statistique descriptive
Cela renvoie :
Cela renvoie :
C. Chesneau 45
4 Statistique descriptive
On a donc deux sous-nuages de points correspondants aux deux modalités de sex, dans le nuage de
points principal formé de total_bill et tip. Vu la forme allongée de ces deux nuages, une liaison
linéaire est envisageable, suivant les modalités de sex.
Pour une meilleure visibilité, on fait :
Cela renvoie :
On a donc les nuages de points de total_bill et tip suivant les modalités de sex.
C. Chesneau 46
5 Tests statistiques
5 Tests statistiques
Cela renvoie :
ShapiroResult(statistic=0.9197188019752502, pvalue=3.3245434183371003e-10)
Ainsi, on a p-valeur = 3.3245434183371003 × 10−10 , donc p-valeur < 0.001 ; le rejet de la normalité
des données de total_bill est hautement significatif ? ? ?. On avait déjà remarqué cela avec la forme
de l’histogramme associée.
On peut visualiser cela avec le Q-Q plot en faisant :
Cela renvoie :
Clairement, le nuage de points n’est pas bien ajustable par une droite, traduisant la non-normalité des
données.
En revanche, on peut voir si la distribution sous-jacente au logarithme de total_bill, caractère
noté log_total_bill ; suit bien une loi normale. On fait :
C. Chesneau 47
5 Tests statistiques
log_total_bill = [Link](tips.total_bill)
[Link](log_total_bill)
Cela renvoie :
ShapiroResult(statistic=0.9913218021392822, pvalue=0.15760214626789093)
Ainsi, on a p-valeur = 0.15760214626789093, donc p-valeur > 0.05 ; la normalité des données n’est pas
rejetée, on peut donc l’admettre (faute de preuve contraire). On peut visualiser cela avec le Q-Q plot
en faisant :
Cela renvoie :
Cela renvoie :
ShapiroResult(statistic=0.9734253883361816, pvalue=0.07007473707199097)
On a p-valeur = 0.07007473707199097. Comme p-valeur > 0.05, la normalité des données est validée.
Puis, pour la modalité “Male”, on fait :
Cela renvoie :
C. Chesneau 48
5 Tests statistiques
ShapiroResult(statistic=0.9925491809844971, pvalue=0.5931006669998169)
On a p-valeur = 0.5931006669998169). Comme p-valeur > 0.05, la normalité des données est également
validée.
On peut aussi étudier la normalité des données de tip. On fait :
[Link]([Link])
Cela renvoie :
ShapiroResult(statistic=0.897811233997345, pvalue=8.20057563521992e-12)
Ainsi, on a p-valeur = 8.20057563521992 × 10−12 , donc p-valeur < 0.001 ; le rejet de la normalité
des données de tip est hautement significatif ? ? ?. On avait déjà remarqué cela avec la forme de
l’histogramme associée.
En revanche, on peut voir si la distribution sous-jacente au logarithme de log_tip, caractère noté
log_tip ; suit bien une loi normale. On fait :
log_tip = [Link]([Link])
[Link](log_tip)
Cela renvoie :
ShapiroResult(statistic=0.9888471961021423, pvalue=0.05621703341603279)
Ainsi, on a p-valeur = 0.05621703341603279, donc p-valeur > 0.05 (de justesse) ; la normalité des
données n’est pas rejetée, on peut donc l’admettre.
Pour finir, par curiosité, on peut regarder si le lien linéaire entre log_total_bill et log_tip est
plus flagrant que celui entre total_bill et tip. On fait :
Cela renvoie :
C. Chesneau 49
5 Tests statistiques
Cela renvoie :
Ttest_1sampResult(statistic=-2.124481364663343, pvalue=0.034639873897269025)
Ainsi, on a p-valeur = 0.034639873897269025, donc p-valeur ∈]0.01, 0.05] ; on rejette H0 et ce rejet est
significatif ?. On peut donc affirmer, avec un faible risque de se tromper, que la moyenne inconnue
associée à log_total_bill diffère de 2.95.
Un exemple de test unilatéral est le suivant. Si l’on considère les hypothèses : H0 : µ = 2.81 contre
H1 : µ > 2.81, on fait :
C. Chesneau 50
5 Tests statistiques
Cela renvoie :
Ttest_1sampResult(statistic=2.858408457019687, pvalue=0.0023136007319686375)
Cela renvoie :
Ttest_indResult(statistic=-2.393945823575832, pvalue=0.01774056034844257)
Ainsi, on a p-valeur = 0.01774056034844257, donc p-valeur ∈]0.01, 0.05] ; on rejette H0 et ce rejet est
significatif ?. On peut donc affirmer, avec un faible risque de se tromper, que les moyennes inconnues
associées à log_total_bill_Female et log_total_bill_Male diffèrent.
On peut visualiser cette différence en faisant :
Cela renvoie :
C. Chesneau 51
5 Tests statistiques
Mais un test statistique était nécessaire pour confirmer la différence “statistique” de ces moyennes.
Un exemple de test unilatéral est le suivant. Si l’on considère les hypothèses : H0 : µ1 = µ2 contre
H1 : µ1 < µ2 , on fait :
Cela renvoie :
Ttest_indResult(statistic=-2.393945823575832, pvalue=0.008870280174221284)
Ainsi, on a p-valeur = 0.008870280174221284, donc p-valeur ∈]0.001, 0.01] ; on rejette H0 et ce rejet est
très significatif ??. On peut donc affirmer, avec un faible risque de se tromper, que la moyenne inconnue
associée à log_total_bill_Female est strictement inférieure à celle associée à log_total_bill_Male.
Dans le cas d’échantillons appariés (un même échantillon d’individus sur lesquels on mesure un
même caractère dans deux configurations différentes, créant ainsi deux listes de valeurs liés aux
mêmes individus par paires de valeurs), on utilise la syntaxe : [Link].ttest_rel au lieu de
[Link].ttest_ind. Le “rel” signifiant “related”, soit “lié” en français.
C. Chesneau 52
5 Tests statistiques
Pour travailler sur un exemple, on considère les caractères qualitatifs sex et smoker. Les hypothèses
sont : H0 : “les caractères sont indépendants” contre H1 : “les caractères sont dépendants”. Pour mettre
en œuvre le test exact de Fisher, on fait :
t = [Link]([Link], [Link])
[Link].fisher_exact(t)
Cela renvoie :
(1.0121836925960637, 1.0)
Dès lors, la p-valeur est donnée par la deuxième composante du vecteur. On a donc p-valeur = 1.
Comme p-valeur > 0.05, on ne rejette pas l’hypothèse d’indépendance ; on peut l’admettre.
Avec le test du Chi-deux d’indépendance (plus exigeant en hypothèses et moins précis, mais em-
ployons le quand même), on fait :
t = [Link]([Link], [Link])
[Link].chi2_contingency(t)
Cela renvoie :
(0.0,
1.0,
1,
array([[53.84016393, 33.15983607],
[97.15983607, 59.84016393]]))
La p-valeur est donnée par la troisième composante du premier vecteur. On obtient ici aussi p-valeur
= 1, et donc, la même conclusion.
Cela renvoie :
(0.6795702560274505, 2.0794565165370727e-34)
C. Chesneau 53
5 Tests statistiques
Ainsi, on a p-valeur = 2.0794565165370727 × 10−34 , donc p-valeur < 0.001 ; on rejette H0 et ce rejet
est hautement significatif ? ? ?. On peut donc affirmer, avec un faible risque de se tromper, que le lien
linéaire entre log_total_bill et log_tip est fort.
Cela renvoie :
Ainsi, on a p-valeur = 0.09283443293725978. Comme p-valeur > 0.05, on ne rejette pas H0 ; les données
ne nous permettent pas de conclure.
En moins précis mais plus populaire, on aurait pu utiliser le test de Wald. La commande clé est :
statsmodels.statsproportions_ztest.
C. Chesneau 54
5 Tests statistiques
Cela renvoie :
(2.5291375291375293, 0.0017373717860969416)
Cela renvoie :
MannwhitneyuResult(statistic=8045.5, pvalue=0.021196582868044853)
Ainsi, on a p-valeur = 0.021196582868044853, donc p-valeur ∈]0.01, 0.05] ; on rejette H0 et ce rejet est
significatif ?. On peut donc affirmer, avec un faible risque de se tromper, que les caractères quantitatifs
total_bill pour les hommes, et total_bill pour les femmes diffèrent quant à la probabilité de leur
positionnement numérique.
C. Chesneau 55
5 Tests statistiques
Cela renvoie :
sum_sq df F PR(>F)
C(day) 1.770736 3.0 3.1456 0.025847
Residual 45.033979 240.0 NaN NaN
Ainsi, on a p-valeur = 0.025847, donc p-valeur ∈]0.01, 0.05] ; on rejette H0 et ce rejet est significatif
?. On peut donc affirmer, avec un faible risque de se tromper, qu’au moins deux moyennes diffèrent.
Autrement dit, il y a une influence du caractère day sur log_total_bill, et cette influence est signi-
ficative.
On aurait aussi pu faire :
Cela renvoie :
C. Chesneau 56
5 Tests statistiques
La différence entre la première et la dernière moyenne est grande, maos un test était nécessaire pour
valider statistiquement cette différence (les variances étant à prendre en compte).
Pour savoir quels sont les moyennes qui diffèrent le plus, on peut faire des tests “post-hoc”, tels que
les tests de Tukey (HSD) ou les tests de Bonferroni.
Sous l’hypothèse de normalité des données, on rappelle qu’un intervalle de confiance d’une moyenne
inconnue µ d’un caractère quantitatif au niveau 100(1 − α)% est donné par la formule suivante :
s s
iµ = x − tα (ν) √ , x + tα (ν) √ ,
n n
où x est la moyenne des données, s est l’écart-type (corrigé) des données, et tα (ν) est le réel défini par
α
tα (ν) = Q 1 − ; ν
2
C. Chesneau 57
5 Tests statistiques
ddl = n - 1
pp = [Link](proba, ddl)
borneinf = m - pp * [Link](s / n)
bornesup = m + pp * [Link](s / n)
return(borneinf, bornesup)
Dès lors, par exemple, on peut avoir un intervalle de confiance pour la moyenne inconnue associée à
log_total_bill au niveau 99% en faisant :
int_ech_moy(log_total_bill, 0.99)
Cela renvoie :
(2.817366696538782, 2.963253826211445
Ainsi, il y a 99% de chances que la moyenne inconnue associée à log_total_bill appartient à l’inter-
valle (2.817366696538782, 2.963253826211445).
où f est la fréquence du caractère qualitatif binaire égale à la modalité considérée dans les
données, et zα est le réel défini par
α
zα = Q 1 − ,
2
C. Chesneau 58
5 Tests statistiques
où Q(x) désigne la fonction de quantile de la loi normale N (0, 1). Celui-ci, appelé intervalle de
confiance de Wald, est moins précis que l’intervalle de confiance binomiale On peut le coder en
Python de la manière suivante :
def int_ech_prop(frequence, n, niveau = 0.95) :
f = frequence
proba = 1 - (1 - niveau) / 2
pp = [Link](proba)
borneinf = f - pp * [Link](f * (1 - f) / (n - 1))
bornesup = f + pp * [Link](f * (1 - f) / (n - 1))
return(borneinf, bornesup)
Dès lors, à titre d’exemple, on peut avoir un intervalle de confiance pour la proportion inconnue
d’hommes payant l’addition dans le restaurant au niveau 95% en faisant :
int_ech_prop(157 / 244, 244, 0.95)
Cela renvoie :
(0.583219318660705, 0.7036659272409344)
Ainsi, il y a 95% de chances que la proportion inconnue d’hommes payant l’addition dans le
restaurant soit dans l’intervalle (0.583219318660705, 0.7036659272409344).
C. Chesneau 59
6 Élements de classification et de régression
6.1 Classification
Partant des données, on souhaite désormais regrouper les individus qui se ressemblent ; c’est-à-dire,
ceux qui ont des valeurs de caractères proches au sens de la distance mathématique. Pour ce faire,
on peut utiliser l’algorithme de classification ascendante hiérarchique (CAH). La commande clé est
[Link].
Pour travailler sur un exemple, on considère les caractères quantitatifs total_bill, tips et size.
On aimerait faire trois groupes d’individus qui se ressemblent le plus quant à ces caractères. On met
en oeuvre l’algorithme CAH (avec la méthode de Ward et la distance euclidienne) en faisant :
CAH = [Link](tips[["total_bill", "tip", "size"]],method = "ward",
metric = "euclidean")
[Link](CAH, labels = [Link], orientation = "left",
color_threshold = 60)
Cela renvoie :
Les trois groupes d’individus obtenus se distinguent par les couleurs rouges, vert et orange (tous les
individus sont présents sur l’axe ordonné à droite avec leur indices, lesquels sont illisibles car trop collés).
Ils ont été obtenus après une coupure du dendrogramme au seuil de t = 60 (valeur approximative,
t = 71, par exemple, aurait donné le même résultat, le but étant de couper le dendrogramme de sorte
à avoir trois groupes). On peut identifier le groupe d’appartenance de chaque individu en faisant :
C. Chesneau 61
6 Élements de classification et de régression
Cela renvoie :
[3 2 3 3 3 3 2 3 2 2 2 1 2 3 2 3 2 2 2 3 3 3 2 1 3 3 2 2 3 3 2 3 2 3 3 3 2
2 3 1 2 3 2 2 1 3 3 1 3 3 2 2 1 2 3 3 1 3 2 1 3 2 2 3 2 3 2 2 3 2 2 2 3 3
2 2 3 3 3 3 3 3 2 1 2 1 2 3 3 3 3 3 2 3 3 1 3 2 3 2 2 2 1 3 3 2 3 3 3 2 2
2 1 3 3 3 1 2 2 3 2 2 2 2 2 1 2 2 2 3 3 3 2 2 3 2 2 2 2 2 3 1 1 3 2 2 3 2
2 2 2 2 2 3 3 1 1 3 2 2 3 2 2 2 3 3 3 1 2 2 1 2 2 1 3 1 3 2 2 1 1 3 1 3 1
3 3 1 3 3 2 3 3 2 3 2 2 1 2 2 3 2 2 2 3 2 3 1 3 2 1 3 1 2 1 2 3 2 2 1 2 2
2 2 2 2 2 3 2 3 3 2 2 2 2 2 2 1 1 1 3 3 3 3]
Ainsi, par exemple, le premier individu appartient au groupe labellisé 3 (le Groupe 3), le deuxième
individu appartient au groupe labellisé 2 (le Groupe 2), et ainsi de suite.
Une fois cette classification faite, on peut s’intéresser au parangon (individu de chaque groupe
qui est le plus représentatif de son groupe en termes de caractéristiques), le caractère dominant dans
chaque groupe, ou le caractère qui a été le plus discriminant dans les regroupements.
Pour aller plus loin dans les méthodes de classification, voir le module Scikit_learn qui nous
permet, entre autres, d’utiliser la méthodes des k-means, faire des arbres de décision, etc.
On souhaite expliquer un caractère quantitatif en fonction d’un autre caractère quantitatif. Expli-
quer au sens “comportement numérique” du terme. On dispose d’observations de ces deux caractères,
soit deux séries de valeurs, constituant ainsi les données. Si le nuage de points associé laisse présager
un lien linéaire entre ces deux caractères, on peut utiliser le modèle de régression linéaire simple. Ainsi,
en notant Y le caractère à expliquer et X le caractère explicatif, le modèle de régression linéaire simple
est de la forme suivante :
Y = β0 + β1 X + ,
où β0 et β1 sont des coefficients inconnus qu’il faudra estimer avec les données, et est une variable
d’erreur qui modélise une somme de petites erreurs aléatoires provenant de l’expérimentation d’où
provient les données.
Par la méthode des moindres carrés ordinaires, on peut estimer β0 et β1 à l’aide des données,
donnant ainsi les estimations b0 et b1 , respectivement. Dès lors, pour une valeur x de X donnée, une
estimation de la valeur moyenne de Y , notée y, est donnée par l’équation :
y = b0 + b1 x.
C. Chesneau 62
6 Élements de classification et de régression
Aussi, avec x variable, la droite d’équation y = b0 + b1 x est appelée droite de régression ; c’est cette
droite qui fournit un bon ajustement du nuage de points associés.
Pour travailler sur un exemple, on considère les caractères quantitatifs log_total_bill et log_tips
(lesquels ont des distributions sous-jacentes en adéquation avec la loi normale, ce qui est préférable
avec le modèle de régression linéaire). On souhaite expliquer log_total_bill en fonction de log_tips.
Pour avoir le nuage de points associé, on fait :
[Link](log_tip, log_total_bill)
Cela renvoie :
Vu la forme allongée du nuage, un lien linéaire entre log_total_bill et log_tips est envisageable.
On met en œuvre le modèle de régression linéaire simple en faisant :
X = smi.add_constant(log_tip)
model = [Link](log_total_bill, X)
results = [Link]()
print([Link]())
Cela renvoie :
C. Chesneau 63
6 Élements de classification et de régression
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 2.2048 0.052 42.512 0.000 2.103 2.307
tip 0.6838 0.047 14.410 0.000 0.590 0.777
==============================================================================
Omnibus: 15.967 Durbin-Watson: 1.944
Prob(Omnibus): 0.000 Jarque-Bera (JB): 40.213
Skew: 0.195 Prob(JB): 1.85e-09
Kurtosis: 4.950 Cond. No. 4.84
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
On a beaucoup d’informations. Entre autres, on a R-squared = 0.462, qui est assez éloigné de 1, ce
qui signifie que le modèle est plutôt moyen en terme prédictif. La p-valeur associée à β1 est P>|t|
0.000, ce qui signifie que p-valeur < 0.001, et que log_tips à une influence hautement significative
sur log_total_bill. On a également les valeurs de b0 et b1 , avec b0 = 2.2048 et b1 = 0.6838, d’où
l’équation de la droite de régression :
y = 2.2048 + 0.6838x.
Cela renvoie :
Ainsi, pour la valeur 2.5 de log_tips par exemple, une valeur moyenne de log_total_bill s’obtient
en faisant :
C. Chesneau 64
6 Élements de classification et de régression
[Link]((1,2))
Le cadre est similaire à celui de la régression linéaire simple, sauf qu’au lieu d’un seul caractère
explicatif, on en a plusieurs. On dispose d’observations de ces caractères, soit plusieurs séries de valeurs,
constituant ainsi les données. Si les nuages de points associés au caractère que l’on souhaite expliquer
laisse présager un lien linéaire entre ces deux caractères, on peut penser à utiliser le modèle de régression
linéaire multiple. Ainsi, en notant Y le caractère à expliquer et X1 , . . . , Xp les caractères explicatifs, le
modèle de régression linéaire multiple s’écrit sous la forme :
Y = β0 + β1 X1 + . . . + βp Xp + ,
où β0 , β1 . . . , βp sont des coefficients inconnus qu’il faudra estimer avec les données, et est une variable
d’erreur.
Par la méthode des moindres carrés ordinaires, on peut estimer β0 , β1 . . . , βp à l’aide des données,
donnant ainsi les estimations b0 , b1 . . . , bp , respectivement. Dès lors, pour des valeurs x1 , x2 , . . . , xp de
X1 , X2 , . . . , Xp données, une estimation de la valeur moyenne de Y , notée y, est donnée par l’équation :
y = b0 + b1 x1 + . . . + bp xp .
Pour travailler sur un exemple, on considère les caractère quantitatifs log_total_bill, log_tips
et size. On souhaite expliquer log_total_bill en fonction de log_tips et size. On met en œuvre
le modèle de régression linéaire multiple en faisant :
X = [Link]({"const" : 1, "log_tip" : log_tip, "size" : [Link]})
model = [Link](log_total_bill, X)
results = [Link]()
print([Link]())
Cela renvoie :
C. Chesneau 65
6 Élements de classification et de régression
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The smallest eigenvalue is 7.88e-30. This might indicate that there are
strong multicollinearity problems or that the design matrix is singular.
On a beaucoup d’informations. Entre autres, on a R-squared = 0.462, qui est assez éloigné de 1, ce qui
signifie que le modèle est plutôt moyen en terme prédictif. Au vu des p-valeurs, log_tips et [Link]
ont des influences hautement significatives sur log_total_bill. On a également les valeurs de b0 , b1
et b2 , avec b0 = 7.558 × 10−7 , b1 = 0.6838 et b2 = 0.0013, ce qui nous permet de faire des prédictions
sur la valeur moyenne de log_total_bill. Ainsi, pour la valeur de 2.5 pour log_tips et la valeur de
3 pour [Link] par exemple, une valeur moyenne de log_total_bill s’obtient en faisant :
[Link]((1,2.5, 3))
C. Chesneau 66
6 Élements de classification et de régression
Dès lors, on peut utiliser le modèle de régression logistique simple. Ainsi, en notant Y le caractère à
expliquer et X le caractère explicatif, le modèle de régression logistique simple s’écrit sous la forme :
exp(β0 + β1 x)
p(x) = ,
1 + exp(β0 + β1 x)
où p(x) est la probabilité que Y soit égale à une modalité de référence, codée par 1 en toute circonstance,
l’autre par 0 sachant que X vaut x, et β0 et β1 sont des coefficients inconnus qu’il faudra estimer avec
les données.
Par la méthode du maximum de vraisemblance, on peut estimer β0 et β1 à l’aide des données,
donnant ainsi les estimations b0 et b1 , respectivement. Dès lors, pour une valeur x de X donnée, une
estimation de p(x) est est donnée par l’équation :
exp(b0 + b1 x)
p∗ (x) = ,
1 + exp(b0 + b1 x)
On peut alors faire des prédictions sur Y : si p∗ (x) dépasse 0.5, alors Y a plus de chances d’être égale
à 1 (codant la modalité de référence), qu’à 0 (codant l’autre modalité).
Pour travailler sur un exemple, on considère le caractère qualitatif sex et le caractère quantitatif
log_total_bill. On souhaite expliquer sex en fonction de log_totall_bill. On met en œuvre le
modèle de régression logistique simple en faisant :
tips["sex"] = [Link]()[0] # Codant ainsi ‘‘Female’’ en 0, et ‘‘Male’’ en 1
X = smi.add_constant(log_total_bill)
logisticReg = [Link]([Link], X).fit()
print([Link]())
Cela renvoie :
C. Chesneau 67
6 Élements de classification et de régression
Au vu des p-valeurs, notamment celle associée à β1 , log_totall_bill a une influence significative sur
sex. De plus, les coefficients β0 et β1 ont été estimés par b0 = −1.5601 et b1 = 0.7491, respectivement.
On peut alors faire des prédictions en faisant :
[Link]((1,2.5))
Cela renvoie : array([0.57755338]). Ainsi, on a p∗ (x) = 0.57755338 > 0.5 (de justesse), donc un
individu vérifiant log_total_bill égal à 2.5 a plus de chances d’être un homme qu’une femme.
On peut mettre en œuvre la régression logistique multiple en adaptant les formules et commandes
précédentes. Pour allez plus loin, on peut s’intéresser à la matrice de confusion (à partir d’un jeu de
données d’entraînement et d’un jeu de données test ou pas), analyser la performance du modèle avec
la courbe ROC, des pseudo R2 , etc.
C. Chesneau 68