Statistiques descriptives

Description bivariée

Frédéric Blanchard

Résumé

Module de première année de BUT informatique, Reims. TP de statistiques descriptives.

Étudier les variables indépendamment les unes des autres permet de comprendre comment les valeurs de chaque variable sont distribuées. Il est toutefois possible que des liens existent entre deux variables observées sur les mêmes individus.

On utilise les outils des statistiques descriptives bivariées pour observer la liaison entre deux variables.

Les outils dépendent évidemment de la nature des variables impliquées (et de la nature de la liaison recherchée).

1 Quantitative Vs. Quantitative

Comme souvent, le traitement des variables quantitatives est plus « simple ».

Le plus trivial des outils, mais pas le moins efficace d’entre eux, est sans doute la représentation en diagramme de dispersion.

1.1 Diagramme de dispersion

L’idée du diagramme de dispersion consiste à :

Avec matplotlib, on va utiliser la fonction scatter dont les deux premiers arguments correspondent respectivement à la liste des abscisses des points (c’est-à-dire la première variable) et à la liste de leurs ordonnées (la deuxième variable).

import matplotlib.pyplot as plt
# Données
data_v1 = [3.12, 8.01, 4.99, 2.3, 5.39]
data_v2 = [12.5, 1.08, 7.44, 4.56, 9.65]
# Tracé du diagramme de dispersion
plt.scatter(data_v1, data_v2)
# Paramètres graphiques
plt.title('Diagramme de dispersion')   # Titre du graphique
plt.xlabel('V1')                       # Label du premier axe
plt.ylabel('V2')                       # Label du second
plt.axis('equal')                      # Ratio d'échelle des deux axes à 1
plt.grid()                             # Ajout d'une grille
# Affichage
plt.show()

png

Exercice LIAISON

À partir des couples de variables suivants, générer un diagramme de dispersion et essayer d’intuiter la présence ou non d’un lien entre les deux variables, et le cas échéant, la nature de ce lien.

# DATASET 1
data1_v1 = [-0.98, 1.81, 1.07, 1.8, 1.79, -0.56, 1.64, -0.03, 0.11, -0.85, -1.53, -1.47, 1.93, -0.35, -1.15, -0.84, 0.12, -0.35, -0.55, 0.84, -1.55, 1.99, 0.31, -1.0, -1.34, -0.43, 1.67, 0.07, -0.28, -0.33, 0.96, -0.93, -1.67, -0.3, -0.56, 1.95, 1.25, -0.57, 0.58, -1.87, -0.41, 0.08, 1.65, -0.02, -1.84, -0.15, -0.62, 1.14, -1.11, -0.16]
data1_v2 = [-3.21, 2.88, 2.34, 3.83, 3.35, -1.13, 2.84, -1.52, 1.49, -1.61, -3.91, -2.82, 4.38, -0.46, -1.05, -1.23, 1.2, -0.25, -1.62, 0.8, -3.76, 4.13, -0.7, -3.17, -3.59, -0.4, 2.31, 0.12, -0.65, -0.98, 1.84, -2.83, -4.32, -1.6, -1.27, 4.18, 3.12, -0.94, 3.54, -3.66, -0.43, 0.23, 3.36, -1.6, -3.48, 0.58, -0.51, 2.42, -2.1, -0.86]

# DATASET 2
data2_v1 = [0.79, -1.07, 1.87, 1.06, 0.23, 0.93, 0.76, 0.93, 1.37, 0.65, 0.02, -0.97, 0.95, -1.87, 1.9, 1.68, 1.38, 1.06, -1.39, 0.86, -0.25, -1.63, -1.46, 0.53, -1.47, -1.33, -1.46, -1.65, 0.64, 1.54, 0.21, 0.21, -0.92, -0.44, -0.58, -0.18, 1.53, -1.97, -0.22, -1.96, -1.13, -0.48, 0.87, 0.05, -0.83, 0.78, 1.06, -1.09, 1.71, 1.44]
data2_v2 = [-0.28, 1.41, 1.26, 0.79, -0.75, -1.51, -1.26, 1.27, -1.32, 0.08, 1.42, -1.09, 1.47, -1.16, -0.96, -1.34, 0.34, 0.83, -1.61, -0.86, 1.34, 1.57, -1.0, 0.5, -1.96, 1.45, -1.21, 0.19, -1.09, -1.44, 0.52, 0.21, 0.97, -1.96, -1.03, 1.96, 0.88, 1.98, -0.37, 0.98, -0.28, 1.48, -0.04, -1.98, -1.76, -1.72, 1.27, 0.27, 1.76, -1.64]

# DATASET 3
data3_v1 = [-1.42, -1.06, -0.2, 0.68, 1.34, -0.93, -1.44, -1.03, 0.33, 0.26, 1.05, -0.09, -0.7, 1.6, -1.67, 0.09, -0.77, 1.92, 0.09, 0.43, 0.4, -1.7, -0.51, -1.53, -1.54, 1.43, 0.31, -0.99, -1.35, -1.62, 1.66, -0.33, -0.89, -0.06, -0.72, 1.21, 1.77, 1.23, 1.03, 0.77, 0.07, -1.52, -1.82, 0.71, -0.66, 1.73, 0.73, -0.26, -1.65, -0.53]
data3_v2 = [2.21, 1.08, 0.3, 0.58, 1.89, 0.75, 2.25, 1.33, 0.08, -0.12, 1.22, -0.02, 0.4, 2.5, 2.74, -0.23, 0.45, 3.95, -0.15, 0.24, -0.15, 2.8, 0.03, 2.55, 2.37, 2.02, -0.05, 1.04, 2.0, 2.79, 2.98, 0.08, 0.86, -0.1, 0.58, 1.46, 3.19, 1.54, 1.06, 0.68, 0.09, 2.37, 3.4, 0.51, 0.43, 3.0, 0.37, 0.03, 2.62, 0.3]

# DATASET 4
data4_v1 = [1.1203136497073731, 1.7373078036934886, 2.368335223083779, 0.8730512267529372, -0.6624678143623997, 0.7428506107657022, -4.079893829055984, 3.5493465945904843, 2.4991307541783034, 1.9263584960720843]
data4_v2 = [5.758060834411365, 4.425462343941218, 0.043567920636212065, 4.714385829386762, 2.175717240926681, 1.463516586734358, 3.5715008567734836, 0.6925053961721359, 1.2313379873122037, 4.152430119150692]

# DATASET 5
data5_v1 = [0.741180954897479, 1.8660254037844384, 1.0, 0.9594929736144974, 0.2928932188134524, 0.8412535328311812, -0.9594929736144974, 0.6548607339452851, -0.142314838273285, 1.4999999999999998, 0.0, -0.8412535328311811, 0.41541501300188644, 1.9659258262890682, 2.0, -0.4154150130018863, 0.14231483827328512, 0.9999999999999999, 0.03407417371093169, -1.0, 1.7071067811865475, 0.4999999999999999, 1.2588190451025207, 0.1339745962155613, -0.654860733945285]
data5_v2 = [-0.4659258262890682, -3.3306690738754696e-16, 0.0, 0.28173255684142967, -0.20710678118654746, 0.5406408174555976, 0.28173255684142967, 0.7557495743542583, 0.9898214418809328, -0.3660254037844387, 0.5, 0.5406408174555978, 0.9096319953545183, 0.24118095489747904, 0.4999999999999999, 0.9096319953545184, 0.9898214418809327, -0.5, 0.24118095489747926, 1.2246467991473532e-16, -0.20710678118654757, -0.3660254037844386, -0.4659258262890683, 0.0, 0.7557495743542583]

En bref DIAGRAMME DE DISPERSION ET FORMES DES LIAISONS

Lorsque les deux variables (observées sur les mêmes individus) à étudier simultanément sont quantitatives on commence par représenter les individus comme des points dans un espace muni d’un repère dont l’axe des abscisses utilise la première variable, et l’axe des ordonnées, la seconde.

Cette représentation graphique permet alors d’observer des formes. Une « forme » est tout ce qui ne semble pas être dû au hasard. La forme peut-être :

1.2 Liaison

Comme nous venons de le voir il existe différents types de liaisons entre deux variables quantitatives. Une liaison se caractérise par :

1.3 Liaison linéaire

La liaison la plus simple à détecter entre deux variables quantitatives est le lien linéaire. Visuellement, il s’observe sur le diagramme de dispersion lorsque la répartition des points a grosso modo l’allure d’une droite (le lien est alors une fonction affine).

Le coefficient de corrélation linéaire (de Bravais-Pearson) permet de quantifier la force de ce type de lien. Si on note \((x_1, x_2, \ldots, x_n)\) la série associée à la première variable (appelons-la \(X\)) et \((y_1, y_2, \ldots, y_n)\) celle associée à la seconde (\(Y\)), le coefficient de corrélation linéaire (\(r\)) se calcule de la manière suivante :

\[r(X,Y) = \displaystyle \frac{\frac{1}{n}\sum_{i=1}^{n} (x_i - \bar{x})\times (y_i - \bar{y})}{\sigma_X . \sigma_Y} = \frac{Cov(X,Y)}{\sigma_X.\sigma_Y}\]

Autrement dit :

Ce coefficient est à valeurs dans \([-1,1]\).

Exercice COEFFICIENT DE CORRÉLATION LINÉAIRE

  1. Écrire une fonction coefcor(x, y) qui retourne le coefficient de Bravais-Pearson à partir de deux listes x et y.

Exemples :

coefcor([1,2,3,4],[2,4,6,8])
0.9999999999999998
coefcor([1,2,3,1,2,3,1,2,3],[1,1,1,2,2,2,3,3,3])
0.0
coefcor([1,2,3,4],[3,2,1,0])
-0.9999999999999998
  1. En vous aidant de cette fonction, quelles sont les variables qui vous semblent corrélées linéairement ?

1.4 Liaison non-linéaire

Un coefficient de corrélation linéaire proche de 0 signifie qu’il n’y a pas de lien linéaire entre les variables. Il ne signifie toutefois pas qu’il n’y a pas de lien (on parle alors éventuellement de lien non-linéaire).

Par ailleurs, même si on a tendance à l’oublier en pratique, le coefficient de Bravais-Pearson présuppose que les variables sont distribuées normalement (suivant une loi normale).

dans ces deux situations on peut avoir recours au coefficient de corrélation de rangs de Spearman, défini par :

\[\rho(X,Y) = r(R_X, R_Y)\]

\(R_X\) et \(R_Y\) sont les variables X et Y transformées en rangs (en remplaçant chaque valeur par son rang dans la série triée par ordre croissant).

Autrement dit, pour calculer le \(\rho\) de Spearman :

Le coefficient de corrélation de Spearman informe sur la monotonie du couple \((X,Y)\).

Exercice COEFFICIENT DE CORRÉLATION DE RANGS DE SPEARMAN

Écrire une fonction coefspearman(x, y) qui calcule le coefficient de corrélation de rangs de Spearman à partir des deux séries x et y.

Exemple :

coefspearman([1, 2, 3, 4, 5, 6, 7],[1, 4, 8, 16, 25, 36, 49])
1.0
print(coefspearman([-4, -3, -2, -1, 0, 1, 2, 3, 4],[16, 9, 4, 1, 0, 1, 4, 9, 16]))
print(coefspearman2([-4, -3, -2, -1, 0, 1, 2, 3, 4],[16, 9, 4, 1, 0, 1, 4, 9, 16])) # deuxième formulation (implémentation facultative)
0.0
0.033333333333333326
coefspearman([1,2,3,4],[8,8,8,8])
coefspearman2([1,2,3,4],[8,8,8,8])
0
coefspearman([-7, -6, -5, -4, -3, -2, -1],[49, 36, 25, 16, 9, 4, 1])
-1.0

En bref

Pour étudier un éventuel lien entre deux variables quantitatives,

2 Quantitative Vs. Qualitative

Lorsque l’on souhaite étudier les liens entre une variable qualitative et une variable quantitative, on utilise les outils de description univariée sur la quantitative, restreinte à chaque modalité de la qualitative, et on tente d’observer d’éventuelles différences.

Par exemple, supposons que nous disposions d’une variable décrivant la moyenne au premier semestre de BUT1 d’une promo, et d’une variable décrivant l’éditeur préféré de chaque étudiant parmi VSCode, Atom, Vim et Notepad.

Étudier un éventuel lien entre ces deux variables passe par l’étude de la note, dans chaque sous-ensemble d’individus associé à une modalité de la seconde variable. Ainsi on pourrait calculer, par exemple :

On pourrait aussi juxtaposer les boites-à-moustaches des sous-séries correspondantes.

On pourrait enfin choisir de discrétiser la quantitative et utiliser les outils de la section suivante.

Exercice SOUS-ÉCHANTILLONS ASSOCIÉS AUX MODALITÉS

Écrire une fonction split_by(x, y) qui retourne un dictionnaire d tel que d[m] contient les élements de la série x, dont la position correspond à la modalité dans la série y.

x = [6.1, 2.68, 3.35, 9.2, 9.75, 4.46, 1.99, 8.76, 2.52, 3.59, 4.12, 2.62, 8.01, 9.36, 7.03, 6.31, 7.49, 9.32, 9.89, 4.69, 6.41, 8.3, 4.15, 8.22, 6.03, 7.0, 8.37, 2.38, 7.07, 0.82, 3.06, 3.82, 4.0, 3.62, 4.76, 2.68, 2.79, 6.84, 8.25, 6.1]
y = ['A', 'B', 'A', 'A', 'B', 'A', 'B', 'A', 'A', 'B', 'A', 'B', 'A', 'A', 'B', 'A', 'B', 'A', 'A', 'B', 'A', 'B', 'A', 'A', 'B', 'A', 'B', 'A', 'A', 'B', 'A', 'B', 'A', 'A', 'B', 'A', 'B', 'A', 'A', 'B']
print(len(x),len(y))
print(split_by(x, y))
40 40
{'A': [6.1, 3.35, 9.2, 4.46, 8.76, 2.52, 4.12, 8.01, 9.36, 6.31, 9.32, 9.89, 6.41, 4.15, 8.22, 7.0, 2.38, 7.07, 3.06, 4.0, 3.62, 2.68, 6.84, 8.25], 'B': [2.68, 9.75, 1.99, 3.59, 2.62, 7.03, 7.49, 4.69, 8.3, 6.03, 8.37, 0.82, 3.82, 4.76, 2.79, 6.1]}

Exercice DESCRIPTION DES SOUS-DISTRIBUTIONS

Écrire une fonction describe_by(x, y) qui affiche un tableau des principaux indicateurs calculés sur x pour chaque modalité de y.

                      A    B
Moyenne         :  6.05 5.05
Médiane         :  6.36 4.72
Écart-type      :  2.44 2.54
Coef. de var.   :   0.4  0.5
Étendue         :  7.51 8.93
Éc. interquart. :  4.42 4.52
Prem.  quartile :  3.81 2.74
Trois. quartile :  8.23 7.26

Pour dessiner des boîtes à moustaches en fonction des modalités de la variable qualitative, nous allons utiliser seaborn, plus pratique que matplotlib :

import seaborn as sns
d = split_by(x, y)
plt.figure()
sns.boxplot(
    data=[d[k] for k in d],
    showmeans=True,
)
plt.xlabel("Modalité de y")
plt.ylabel("x")
plt.xticks(plt.xticks()[0],['A','B'])
plt.show()

png

On peut aussi comparer les histogrammes de ces sous-groupes :

import pandas
plt.figure()
sns.histplot(data=pandas.DataFrame({'x':x, 'y':y}), x='x', hue='y', bins=[0,2,4,6,8,10])
plt.show()
/home/fred/.local/lib/python3.11/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead
  if pd.api.types.is_categorical_dtype(vector):
/home/fred/.local/lib/python3.11/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead
  if pd.api.types.is_categorical_dtype(vector):
/home/fred/.local/lib/python3.11/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead
  if pd.api.types.is_categorical_dtype(vector):
/home/fred/.local/lib/python3.11/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead
  if pd.api.types.is_categorical_dtype(vector):
/home/fred/.local/lib/python3.11/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.
  with pd.option_context('mode.use_inf_as_na', True):

png

plt.figure()
sns.histplot(d['A'],bins=[0,2,4,6,8,10])
plt.title('A')
plt.show()
plt.figure()
plt.title('B')
sns.histplot(d['B'],bins=[0,2,4,6,8,10])
plt.show()
/home/fred/.local/lib/python3.11/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead
  if pd.api.types.is_categorical_dtype(vector):
/home/fred/.local/lib/python3.11/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.
  with pd.option_context('mode.use_inf_as_na', True):

png

/home/fred/.local/lib/python3.11/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead
  if pd.api.types.is_categorical_dtype(vector):
/home/fred/.local/lib/python3.11/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.
  with pd.option_context('mode.use_inf_as_na', True):

png

Comment interpréter ces graphiques ? Si les histogrammes ou les boîtes à moustaches des valeurs de la variable quantitative semblent montrer des différences significatives entre les groupes définis par les modalités de la qualitative, on peut suspecter qu’il y a un lien entre les deux.

Pour le prouver, il faudra alors effectuer des tests statistiques qui sortent du cadre de ce module (voir BUT3).

En bref

Lorsqu’une variable est quantitative et l’autre qualitative, on utilise les modalités de la qualitative pour définir des sous-groupes d’individus (qui partagent la même modalité au sein d’un même sous-groupe).

On étudie ensuite, dans chaque sous-groupe, la distribution des valeurs de la variable quantitative.

En comparant ces distributions (de manière graphique ou numérique), on peut alors déceler d’éventuelles différences permettant de suspecter l’existence d’un lien entre les deux variables.

3 Qualitative Vs. Qualitative

Lorsque les deux variables sont qualitatives, il est nécessaire de les croiser en construisant un tableau de contingence. Le tableau de contingence est un tableau à double-entrée dans lequel :

Exercice TABLEAU DE CONTINGENCE

Écrire une fonction contingency_table(var1, var2) qui prend en entrée deux séries associées à deux variables qualitatives et qui retourne le tableau de contingence entre ces deux variables.

On représentera la table de contingence à l’aide d’un dictionnaire tel que (si on l’appelle \(D\) par exemple) : \(D[(m_i,m^{'}_j)]\) contient le nombre d’invidus qui ont \(m_i\) comme valeur pour la première variable et \(m_j\) pour la seconde.

Exemple :

var1 = ['tata', 'titi', 'titi', 'tata', 'toto', 
        'toto', 'toto', 'tata', 'toto', 'titi', 
        'tata', 'tata', 'tata', 'titi', 'toto', 
        'tata', 'tata', 'toto', 'titi', 'titi', 
        'toto', 'toto', 'titi', 'tata', 'tata', 
        'titi', 'titi', 'toto', 'toto', 'tata', 
        'toto', 'titi', 'toto', 'toto', 'titi', 
        'toto', 'toto', 'toto', 'tata', 'titi', 
        'tata', 'tata', 'titi', 'titi', 'toto', 
        'toto', 'titi', 'titi', 'toto', 'tata']

var2 = ['foo', 'foo', 'bar', 'bar', 'bar', 'foo', 'bar', 'foo', 'foo', 'bar', 
        'foo', 'foo', 'foo', 'foo', 'bar', 'bar', 'foo', 'foo', 'bar', 'foo', 
        'bar', 'foo', 'foo', 'foo', 'foo', 'foo', 'bar', 'foo', 'foo', 'bar', 
        'foo', 'foo', 'foo', 'bar', 'bar', 'foo', 'foo', 'bar', 'bar', 'foo', 
        'bar', 'foo', 'foo', 'foo', 'bar', 'bar', 'bar', 'bar', 'foo', 'bar']

print(contingency_table(var1,var2))
{('titi', 'bar'): 7, ('titi', 'foo'): 9, ('toto', 'bar'): 8, ('toto', 'foo'): 11, ('tata', 'bar'): 6, ('tata', 'foo'): 9}

Je vous prête ma fonction pretty print dédiée à l’affichage d’une table de contingence :

def pprint_contable(ct):
    M1 = list(set([k[0] for k in ct.keys()]))
    M2 = list(set([k[1] for k in ct.keys()]))
    maxnm1 = max([len(str(m)) for m in M1])
    maxnm2 = max([len(str(m)) for m in M2])
    maxnval = max([len(str(v)) for v in ct.values()])
    txt  = '+' + '-'*(maxnm1+2) + '+' + ('-'*(maxnm2+2) + '+')*len(M2) + '\n'
    txt += '|' + ' '*(maxnm1+2) + '|' + ''.join([""+str(m2).rjust(maxnm2+1)+""+' |' for m2 in M2]) + '\n'
    txt += '+' + '-'*(maxnm1+2) + '+' + ('-'*(maxnm2+2) + '+')*len(M2) + '\n'
    for m1 in M1:
        txt += '| ' +""+ str(m1).ljust(maxnm1+1) +""+ '|' + ''.join([str(ct[(m1,m2)]).rjust(maxnm2+1)+' |' for m2 in M2]) + '\n'
        txt += '+' + '-'*(maxnm1+2) + '+' + ('-'*(maxnm2+2) + '+')*len(M2) + '\n'
    print(txt)
    return None

pprint_contable(contingency_table(var1,var2))
+------+-----+-----+
|      | bar | foo |
+------+-----+-----+
| titi |   7 |   9 |
+------+-----+-----+
| toto |   8 |  11 |
+------+-----+-----+
| tata |   6 |   9 |
+------+-----+-----+

On a placé des effectifs dans la table de contingence, mais on pourrait aussi calculer des fréquences.

Exercice TABLE DES FREQUENCES

Ajouter un argument booléen optionnel freq à la fonction contingency_table qui indique si la fonction doit retourner des effectifs ou des fréquences.

Exemple :

print(contingency_table(var1, var2, freq=False))
{('titi', 'bar'): 7, ('titi', 'foo'): 9, ('toto', 'bar'): 8, ('toto', 'foo'): 11, ('tata', 'bar'): 6, ('tata', 'foo'): 9}
print(contingency_table(var1, var2, freq=True))
{('titi', 'bar'): 0.14, ('titi', 'foo'): 0.18, ('toto', 'bar'): 0.16, ('toto', 'foo'): 0.22, ('tata', 'bar'): 0.12, ('tata', 'foo'): 0.18}
pprint_contable(contingency_table(var1, var2, freq=True))
+------+-----+-----+
|      | bar | foo |
+------+-----+-----+
| titi |0.14 |0.18 |
+------+-----+-----+
| toto |0.16 |0.22 |
+------+-----+-----+
| tata |0.12 |0.18 |
+------+-----+-----+

On appelle distributions marginales les distributions des effectifs de chaque variable, que l’on retrouve à l’aide d’un tableau de contingence.

Concrètement, il s’agit de faire les sommes des lignes et des colonnes de la table de contingence

Exercice DISTRIBUTIONS MARGINALES

Écrire une fonction margin (un booléen) qui prend en argument un tableau de contingence, ainsi qu’un entier valant 0, 1 ou 2, et qui retourne : - les sommes des lignes si l’entier vaut 1 - les sommes des colonnes si l’entier vaut 2 - la somme de toutes les cellules si l’entier vaut 0 ou s’il n’est pas spécifié.

Exemple :

print(margin(contingency_table(var1, var2), m=0))
print(margin(contingency_table(var1, var2), m=1))
print(margin(contingency_table(var1, var2), m=2))
50
{'titi': 16, 'toto': 19, 'tata': 15}
{'bar': 21, 'foo': 29}
print(margin(contingency_table(var1, var2, freq = True), m=0))
print(margin(contingency_table(var1, var2, freq = True), m=1))
print(margin(contingency_table(var1, var2, freq = True), m=2))
1.0
{'titi': 0.32, 'toto': 0.38, 'tata': 0.3}
{'bar': 0.42000000000000004, 'foo': 0.5800000000000001}

L’adaptation suivante de la fonction d’affichage permet d’inclure les distributions marginales (ainsi qu’un argument optionnel pour arrondir les fréquences) :

def pprint_contable(cont, margin1=None, margin2=None, dec=None):
    if margin1 is not None:
        marg1 = margin1.copy()
    else:
        marg1 = None
    if margin2 is not None:
        marg2 = margin2.copy()
    else:
        marg2 = None
    ct = cont.copy()
    if dec is not None:
        for k in ct:
            ct[k] = round(ct[k],dec)
        if marg1 is not None:
            for k in marg1:
                marg1[k] = round(marg1[k],dec)
        if marg2 is not None:
            for k in marg2:
                marg2[k] = round(marg2[k],dec)
    M1 = list(set([k[0] for k in ct.keys()]))
    M2 = list(set([k[1] for k in ct.keys()]))
    maxnm1 = max([len(str(m)) for m in M1])
    maxnm2 = max([len(str(m)) for m in M2])
    maxnval = max([len(str(v)) for v in ct.values()])
    if marg1 is not None:
        maxnval = max([maxnval,max([len(str(v)) for v in marg1.values()])])
    if marg2 is not None:
        maxnval = max([maxnval,max([len(str(v)) for v in marg2.values()])])        
    maxnm2 = max([maxnm2, maxnval, 5])
    maxnm1 = max([maxnm1, 5])
    txt  = '+' + '-'*(maxnm1+2) + '+' + ('-'*(maxnm2+2) + '+')*len(M2) + ('' if marg1 is None else ('-'*(maxnm2+2) + '+') ) +'\n'
    txt += '|' + ' '*(maxnm1+2) + '|' + ''.join(["\u001b[1m\u001b[92m"+str(m2).rjust(maxnm2+1)+"\u001b[0m"+' |' for m2 in M2]) +  ('' if marg1 is None else "\u001b[1m\u001b[94m\u001b[7m"+str('TOTAL').rjust(maxnm2+1)+"\u001b[0m"+' |')+ '\n'
    txt += '+' + '-'*(maxnm1+2) + '+' + ('-'*(maxnm2+2) + '+')*len(M2) + ('' if marg1 is None else ('-'*(maxnm2+2) + '+') ) + '\n'
    for m1 in M1:
        txt += '| ' + "\u001b[1m\u001b[94m"+str(m1).ljust(maxnm1+1)+"\u001b[0m" + '|' + ''.join([str(ct[(m1,m2)]).rjust(maxnm2+1) + ' |' for m2 in M2]) +  ('\n' if marg1 is None else ("\u001b[1m\u001b[94m\u001b[7m"+str(marg1[m1]).rjust(maxnm2+1) +"\u001b[0m"+ ' |' + '\n'))
        txt += '+' + '-'*(maxnm1+2) + '+' + ('-'*(maxnm2+2) + '+')*len(M2) + ('' if marg1 is None else ('-'*(maxnm2+2) + '+') ) + '\n'
    if marg2 is not None:
        txt += '| ' + "\u001b[1m\u001b[92m\u001b[7m"+'TOTAL'.ljust(maxnm1+1) +"\u001b[0m"+ '|' + ''.join(["\u001b[1m\u001b[92m\u001b[7m"+str(marg2[m2]).rjust(maxnm2+1)+"\u001b[0m"+' |' for m2 in M2]) + "\u001b[1m\u001b[7m"+str(sum(marg2.values())).rjust(maxnm2+1)+"\u001b[0m"+' |' + '\n'
        txt += '+' + '-'*(maxnm1+2) + '+' + ('-'*(maxnm2+2) + '+')*len(M2) + ('' if marg1 is None else ('-'*(maxnm2+2) + '+') ) + '\n'
    print(txt)
    return None

pprint_contable(contingency_table(var1, var2))

pprint_contable(contingency_table(var1, var2),
                margin(contingency_table(var1, var2),1),
                margin(contingency_table(var1, var2),2))

pprint_contable(contingency_table(var1, var2, freq=True),
                margin(contingency_table(var1, var2, freq=True),1),
                margin(contingency_table(var1, var2, freq=True),2), dec=2)
+-------+-------+-------+
|       |   bar |   foo |
+-------+-------+-------+
| titi  |     7 |     9 |
+-------+-------+-------+
| toto  |     8 |    11 |
+-------+-------+-------+
| tata  |     6 |     9 |
+-------+-------+-------+

+-------+-------+-------+-------+
|       |   bar |   foo | TOTAL |
+-------+-------+-------+-------+
| titi  |     7 |     9 |    16 |
+-------+-------+-------+-------+
| toto  |     8 |    11 |    19 |
+-------+-------+-------+-------+
| tata  |     6 |     9 |    15 |
+-------+-------+-------+-------+
| TOTAL |    21 |    29 |    50 |
+-------+-------+-------+-------+

+-------+-------+-------+-------+
|       |   bar |   foo | TOTAL |
+-------+-------+-------+-------+
| titi  |  0.14 |  0.18 |  0.32 |
+-------+-------+-------+-------+
| toto  |  0.16 |  0.22 |  0.38 |
+-------+-------+-------+-------+
| tata  |  0.12 |  0.18 |   0.3 |
+-------+-------+-------+-------+
| TOTAL |  0.42 |  0.58 |   1.0 |
+-------+-------+-------+-------+

Vérifier qu’on obtient les mêmes distributions avec get_distr du TP précédent.

3.1 Coefficients d’association

On peut calculer, à partir du tableau de contingence, des indicateurs permettant d’évaluer la présence d’un lien entre les deux variables qualitatives correspondantes.

Ils reposent, pour la plupart, sur le calcul d’une distance appelée « du \(\chi^2\) » (prononcer “khi-deux”). Cette distance mesure l’écart entre le tableau de contingence observé et celui qu’on aurait obtenu si les deux variables étaient indépendantes.

Comment calculer ce « tableau théorique » ?

Si les variables \(X_1\), et \(X_2\) étaient indépendantes, la proportion d’individus ayant \(m_1\) et \(m_2\) comme valeurs respectives devrait être \(p_{m_1} \times p_{m_2}\), où \(p_{m_1}\) représente la proportion de \(m_1\) observée dans \(X_1\) et \(p_{m_2}\) représente la proportion de \(m_2\) observée dans \(X_2\).

On peut alors calculer \(\chi^2(X_1,X_2)\) à l’aide de l’algorithme suivant :

Soit N le nombre d'individus
Extraire les distributions marginales de X1 et X2
d2 = 0
Pour chaque modalité m1 de X1 :
    Pour chaque modalité m2 de X2 :
        On note n_obs l'effectif observé ayant m21 et m2 comme modalités pour X1 et X2 :
        n_obs = effectif lu dans le tableau de contingence
        On note n_the l'effectif théorique 
        (et nm1 l'effectif de m1 dans X1, nm2 l'effectif de m2 dans X2) :
        n_the = nm1 * nm2 / N
        d2 := d2 + (n_obs - n_the)^2 / n_the
Retourner d2
def dchi2(cont):
    marg1 = margin(cont, 1)
    marg2 = margin(cont, 2)
    N = margin(cont, 0)
    d2 = 0
    for m1 in marg1.keys():
        for m2 in marg2.keys():
            n_the = (marg1[m1] * marg2[m2]) / N
            n_obs = cont[(m1,m2)]
            d2 += ((n_obs - n_the)**2) / n_the
    return d2

Exemple :

print(dchi2(contingency_table(var1, var2)))
0.04483190735459339

La distance du \(\chi^2\) sert à définir plusieurs coefficients d’association de deux variables qualitatives et notamment, le V de Cramer :

\[V(X_1, X_2) = \sqrt{\frac{\chi^2}{n\times (min(l,c)-1)}}\]

\(n\) est le nombre d’individus, \(l\) le nombre de modalités de \(X_1\) et \(c\) le nombre de modalités de \(X_2\).

Exercice V DE CRAMER

Écrire une fonction v_cramer qui retourne le \(V\) de Cramer de deux variables qualitatives passées en argument.

Exemple :

print(v_cramer(var1, var2))
0.02994391669591451

En bref

Lorsqu’on étudie deux variables qualitatives, il est nécessaire de construire au préalable un tableau de contingence.

Ce tableau croise les modalités des deux variables et détermine les effectifs (ou les fréquences) d’individus partageant ces couples de modalités.

À partir de ce tableau de contingence, on peut retrouver les distributions marginales (i.e. les distributions groupées de chacune des deux variables).

La distance du \(\chi^2\) calcule l’écart entre ce tableau, observé sur les données, et celui qu’on obtiendrait, en théorie, si les variables étaient indépendantes.

Le V de Cramer transforme cette distance en une quantité interprétable de la façon suivante :

4 Problèmes et mise en pratique

Exercice POLÉMIQUE À SPRINGFIELD

La ville de Springfield s’est équipée d’un logiciel édité par la société USURPA CORP qui permet d’affecter les jeunes dans le supérieur, en fonction de leurs souhaits. Hélas, les résultats font polémique. Le logiciel semble être inéquitable.

L’institut municipal de la statistique de Springfield a pu collecter des informations sur les deux lycées de la ville. Tahiti Bob, l’opposant au maire estime que les jeunes filles sont défavorisées par rapport aux garçons. Diamond Joseph “Joe” Quimby, le maire en place, rétorque que les chiffres montrent au contraire que les filles obtiennent plus volontiers leurs vœux.

On a pu nous procurer les chiffres et les protocoles pour pouvoir refaire les calculs et trancher.

Remarque : ‘Reussite’ = obtention d’une affectation dans le supérieur ; ‘Echec’ = pas d’affectation.

Voici les données. Elles se présentent sous la forme d’une serie de t-uplets, représentant chacun un élève. Le premier élément du t-uplet indique son sexe, le deuxième sont établissement (lycée A ou B), et enfin le troisième s’il a réussi au bac.

data = [('Fille', 'A', 'Echec'),     ('Fille', 'A',  'Echec'),     ('Garcon', 'A', 'Echec'), 
        ('Fille', 'A', 'Echec'),     ('Fille', 'A',  'Echec'),     ('Fille', 'B', 'Reussite'), 
        ('Garcon', 'B', 'Reussite'), ('Fille', 'B',  'Reussite'),  ('Fille', 'B', 'Reussite'), 
        ('Garcon', 'B', 'Reussite'), ('Fille', 'A',  'Reussite'),  ('Fille', 'A', 'Echec'), 
        ('Fille', 'A', 'Echec'),     ('Fille', 'A',  'Echec'),     ('Fille', 'A', 'Echec'), 
        ('Fille', 'B', 'Reussite'),  ('Garcon', 'B', 'Reussite'),  ('Garcon', 'A', 'Echec'), 
        ('Garcon', 'B', 'Reussite'), ('Garcon', 'B', 'Reussite'),  ('Garcon', 'B', 'Echec'), 
        ('Garcon', 'A', 'Echec'),    ('Garcon', 'B', 'Reussite'),  ('Garcon', 'B', 'Reussite'), 
        ('Fille', 'B', 'Reussite'),  ('Garcon', 'A', 'Echec'),     ('Garcon', 'B', 'Reussite'), 
        ('Garcon', 'A', 'Echec'),    ('Garcon', 'B', 'Reussite'),  ('Fille', 'A', 'Echec')]

Attention : si vous voulez utiliser les fonctions précédentes, il ne faut pas oublier les cellules « vides » (d’effectif 0)

  1. Première méthode

Commencer par regrouper les données par lycée puis compléter :

Conclure.

  1. Deuxième méthode

Compléter directement, sans regroupement préalable :

Conclure.

  1. QUI A RAISON ? Joe Quimby ou Tahiti Bob ?

Exercice ALIMENTATION ET PERFORMANCES

En 2011, les résultats d’une étude, menée sur 400 personnes, pendant 5 ans, a été publiée. L’objectif de cette étude était d’analyser un éventuel lien entre la consommation de produits gras et sucrés avec les performances intellectuelles. Les résultats, disponibles en ligne ont été convertis ici en t-uplets (la première valeur est le score global aux tests réalisés pendant ces cinq années par chaque individu, et le second est le nombre moyen de viennoiseries consommées en moyenne chaque semaine par chaque individu).

data = [(669, 7.97), (606, 12.77), (762, 5.39), (825, 6.03), (316, 9.04), (759, 4.54), (359, 10.8), (767, 7.86), (195, 4.29), (743, 9.1), (230, 8.34), (405, 9.5), (141, 6.11), (398, 10.89), (466, 7.87), (456, 11.43), (439, 11.4), (577, 5.32), (403, 9.41), (987, 12.87), (672, 6.81), (408, 8.68), (285, 9.89), (451, 8.45), (754, 5.28), (541, 6.88), (663, 8.04), (625, 2.19), (390, 8.78), (397, 7.3), (477, 4.6), (892, 6.38), (616, 9.76), (489, 10.67), (302, 10.33), (545, 9.6), (288, 3.16), (893, 12.92), (805, 7.03), (1067, 12.62), (1091, 10.05), (393, 9.37), (805, 5.81), (1064, 8.75), (642, 7.8), (649, 8.07), (452, 3.09), (468, 8.69), (569, 5.65), (983, 13.18), (686, 9.6), (530, 6.95), (208, 5.56), (637, 7.82), (494, 7.28), (391, 8.75), (522, 12.11), (404, 9.58), (573, 12.54), (1086, 12.42), (884, 6.32), (975, 7.66), (533, 9.52), (406, 9.43), (737, 9.17), (902, 6.41), (477, 11.62), (1007, 11.21), (579, 4.83), (840, 6.78), (291, 9.08), (470, 3.2), (1035, 12.14), (1089, 9.55), (158, 5.62), (211, 8.24), (303, 1.67), (660, 3.57), (292, 9.04), (313, 4.96), (794, 5.68), (1088, 10.69), (647, 7.74), (658, 8.14), (1004, 12.87), (944, 12.6), (658, 7.93), (643, 7.81), (464, 7.98), (658, 7.74), (547, 3.9), (760, 13.31), (666, 13.09), (942, 6.41), (474, 1.51), (990, 12.15), (358, 1.56), (879, 5.57), (186, 8.05), (1062, 11.23), (759, 8.79), (191, 2.81), (656, 7.82), (281, 9.41), (817, 7.14), (973, 12.83), (600, 12.74), (1016, 8.14), (880, 5.58), (806, 5.82), (637, 2.58), (1091, 10.53), (463, 8.41), (933, 6.25), (925, 12.72), (293, 9.07), (396, 9.45), (398, 9.4), (1046, 8.46), (431, 7.1), (543, 6.13), (1018, 11.43), (632, 6.7), (411, 9.49), (540, 9.57), (798, 5.71), (157, 7.8), (446, 8.45), (889, 6.7), (854, 7.33), (1066, 11.12), (138, 7.58), (204, 2.08), (428, 3.02), (1074, 12.57), (931, 13.38), (1014, 12.87), (966, 12.41), (192, 4.8), (648, 8.17), (404, 9.4), (640, 8.07), (570, 5.63), (368, 2.94), (635, 12.95), (638, 7.84), (1023, 12.7), (506, 11.95), (1051, 11.37), (290, 3.14), (857, 7.31), (940, 7.29), (402, 9.49), (1098, 12.17), (649, 8.0), (658, 3.52), (472, 11.55), (399, 9.33), (936, 12.63), (1084, 10.85), (393, 9.55), (805, 5.39), (178, 8.02), (502, 3.41), (1087, 10.7), (1110, 11.58), (174, 5.05), (395, 9.58), (653, 7.85), (201, 8.17), (823, 13.23), (1092, 9.83), (805, 5.79), (397, 9.61), (828, 13.22), (639, 2.75), (631, 2.45), (1015, 12.81), (530, 10.2), (844, 13.18), (1051, 12.76), (659, 8.01), (684, 13.16), (953, 12.51), (539, 6.19), (654, 8.02), (835, 6.1), (573, 5.52), (343, 9.03), (386, 2.94), (1092, 9.96), (837, 6.09), (640, 7.8), (289, 9.15), (659, 7.97), (989, 12.16), (800, 5.52), (995, 13.08), (777, 13.3), (1022, 11.48), (415, 8.62), (189, 2.17), (211, 3.9), (381, 4.64), (166, 2.34), (713, 4.59), (163, 7.88), (706, 6.97), (463, 8.23), (609, 12.81), (193, 8.12), (758, 5.18), (643, 7.78), (119, 6.28), (1073, 8.92), (829, 7.26), (803, 5.51), (382, 8.81), (246, 3.48), (746, 9.06), (643, 2.8), (899, 12.89), (693, 6.91), (297, 5.02), (652, 8.17), (904, 6.88), (301, 3.1), (395, 9.46), (629, 7.82), (969, 7.61), (297, 8.99), (1091, 10.58), (398, 9.5), (845, 6.98), (439, 1.51), (789, 13.29), (459, 8.38), (444, 11.42), (160, 5.32), (196, 5.65), (651, 8.15), (1085, 10.69), (319, 7.77), (659, 7.88), (468, 8.7), (1079, 9.14), (473, 1.51), (752, 5.32), (278, 8.75), (112, 7.21), (1035, 11.61), (651, 3.33), (749, 4.51), (229, 3.62), (506, 7.17), (129, 6.2), (203, 2.99), (382, 10.86), (471, 10.77), (368, 4.69), (127, 7.44), (642, 2.76), (770, 8.05), (193, 8.11), (712, 4.62), (737, 5.45), (871, 6.27), (728, 13.3), (1010, 11.93), (465, 4.39), (916, 6.49), (1037, 8.36), (408, 11.18), (191, 8.11), (298, 3.1), (558, 9.67), (646, 3.02), (192, 4.84), (520, 1.57), (749, 9.0), (632, 7.75), (1064, 12.64), (502, 9.28), (911, 6.94), (475, 1.54), (900, 6.4), (157, 5.57), (392, 9.18), (846, 6.99), (934, 7.22), (784, 4.68), (408, 7.26), (764, 13.31), (496, 10.59), (1021, 12.86), (292, 7.98), (838, 13.19), (838, 6.69), (317, 4.92), (85, 6.85), (790, 4.77), (255, 3.38), (965, 12.82), (344, 9.02), (90, 7.06), (1032, 11.83), (660, 7.87), (933, 12.68), (449, 6.99), (202, 5.58), (355, 1.57), (176, 7.99), (179, 5.79), (635, 12.96), (578, 5.11), (373, 1.54), (113, 6.35), (571, 9.71), (1027, 12.53), (367, 2.92), (539, 12.24), (437, 10.87), (402, 9.38), (1087, 12.36), (454, 1.5), (210, 3.13), (124, 6.23), (658, 8.05), (954, 12.52), (212, 8.24), (868, 6.51), (405, 9.31), (1026, 12.84), (216, 2.01), (335, 2.97), (779, 5.25), (280, 9.69), (550, 3.96), (872, 6.29), (898, 12.92), (491, 6.67), (722, 4.55), (570, 4.49), (786, 4.73), (1058, 8.64), (519, 3.57), (739, 7.32), (495, 10.63), (769, 8.41), (275, 1.77), (891, 6.76), (470, 8.76), (578, 5.32), (600, 6.68), (424, 3.01), (91, 7.1), (389, 8.79), (420, 2.98), (206, 3.94), (305, 7.89), (325, 1.64), (286, 10.03), (550, 9.66), (530, 12.17), (1015, 11.89), (678, 9.66), (847, 6.17), (664, 8.12), (639, 7.79), (570, 5.61), (996, 13.05), (279, 9.59), (387, 9.24), (822, 6.23), (294, 9.0), (424, 7.15), (830, 6.53), (216, 3.3), (223, 2.0), (579, 5.25), (700, 4.69), (1071, 8.91), (382, 9.51), (830, 6.47), (482, 1.52), (920, 12.75), (814, 13.27), (1013, 11.26), (794, 6.94), (521, 6.39), (406, 4.57), (1080, 9.18), (570, 4.4), (592, 12.66), (836, 7.31), (664, 3.65), (562, 4.18), (304, 10.34), (791, 13.31), (163, 5.29)]

À l’aide d’un indicateur bien choisi, déterminer l’association ou l’absence de lien linéaire entre les deux variables.

Que conclure ?

Exercice ASSIDUITÉ ET RÉUSSITE

On dispose d’informations sur une promotion d’élèves décrits par deux variables : la première caractérisant l’assiduité, la seconde caractérisant la qualité de la copie rendue au dernier devoir surveillé. Voici ces données :

v1 = ['Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'Assidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu', 'NonAssidu']
v2 = ['Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Faible', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Moyen', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon', 'Bon']

À l’aide de la fonction v_cramer, déterminer s’il existe un lien entre l’assiduité et les résultats au devoir, ou au contraire si ces variables semblent indépendantes.

Exercice DIVORCES ET MARGARINE

On a relevé, dans le Maine la consommation moyenne mensuelle de margarine, et le taux de divorce (nb/1000) entre 2000 et 2009.

Voici les données :

margarine = [3.719, 3.175, 2.948, 2.404, 2.359, 1.814, 2.087, 2.041, 1.905, 1.678]
divorce = [5, 4.7, 4.6, 4.4, 4.3, 4.1, 4.2, 4.2, 4.2, 4.1]

Les deux séries vous semblent-elles liées ? Diminuer la consommation de margarine pourrait selon vous réduire le taux de divorce ?

Exercice EXERCICE BILAN

À l’aide de l’ensemble des outils vus au cours de ces deux premiers chapitres, proposer une analyse des données suivantes (à récupérer ici https://raw.githubusercontent.com/lgreski/pokemonData/master/Pokemon.csv) :

import csv
rawdata = []
data = dict()
with open('pokemon.csv', newline='') as csvfile:
    spamreader = csv.reader(csvfile, delimiter=',')
    for row in spamreader:
        rawdata.append(row)
for i in range(len(rawdata[0])):
        data[rawdata[0][i]] = []
for l in rawdata[1:]:
    for i in range(len(rawdata[0])):
        data[rawdata[0][i]].append(l[i])
# à vous de jouer...
# toutes les données sont dans le dictionnaire data !

Au delà de l’exploration systématique, les questions suivantes peuvent vous guider dans les traitements à effectuer qui pourraient être intéressants :