Notebook originel: exam22.ipynb
Examen Science des données🔗
Date: 04 janvier 2023
Durée: 2 h
[1]:
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats
Consignes🔗
Créez un répertoire Exam22_NOM_Prenom dans lequel vous travaillerez, et où seront stockés
le notebook jupyter d’analyse (
nom_prenom.ipynb, copié à partir de ce notebook énoncé sans l’extension.orig), que vous complèterez progressivement en ajoutant une ou plusieurs cellules en dessous de chaque question;le package python en développement, selon les instructions ci-dessous.
Vous devez alors mettre ce répertoire sous contrôle git sur un projet dédié sur le serveur https://gitlab.in2p3.fr, et en transmettre l’adresse à y.copin@ipnl.in2p3.fr.
Si, par manque de temps ou de connaissance, vous ne pouvez pas créer un dépôt git, envoyez par mail le notebook et/ou le package (sous forme d’un fichier tar ou zip) à y.copin@ipnl.in2p3.fr (cette solution sera pénalisée dans la notation).
Tests🔗
Ce notebook inclut des tests unitaires vous permettant de tester a minima le code du notebook. Utilisez ces tests pour guider votre développement et vérifier vos résultats. Ne modifiez pas (a fortiori, n’effacez pas) ces tests.
Test de Grubbs🔗
En statistique inférentielle, le test de Grubbs (également connu sous le nom de test du résidu normalisé maximum) est un test utilisé pour détecter une seule valeur aberrante dans un ensemble de données univariées supposées provenir d’une population approximativement normale. (NIST/SEMATECH e-Handbook of Statistical Methods).
Attention:, en raison de potentiels effets d’écrantage (plusieurs valeurs aberrantes peuvent affaiblir la performance du test), il n’est généralement pas approprié d’appliquer séquentiellement un test de valeur aberrante unique pour détecter plusieurs valeurs aberrantes.
Le test de Grubbs est défini pour l’hypothèse suivante:
\(H_{0}\) : il n’y a pas de valeurs aberrantes dans l’ensemble de données;
\(H_{1}\) : il y a exactement une valeur aberrante dans l’ensemble de données.
La statistique du test de Grubbs est définie par :
où \(\bar{y}\) et \(s\) désignent respectivement la moyenne et l’écart type de l’échantillon. Ainsi, \(G\) est le plus grand écart absolu par rapport à la moyenne de l’échantillon en unités de l’écart type de l’échantillon.
Pour le test bilatéral (sans a priori sur la position relative du point abérrant), l’hypothèse \(H_{0}\) est rejetée au niveau de signification \(\alpha\) si
où \(t^{*}_{\alpha/(2N),N-2}\) désigne la valeur critique supérieure de la distribution de Student \(t\) avec \(N - 2\) degrés de liberté et un niveau de signification de \(\alpha/(2N)\).
Dans les cas unilatéraux (tests portant sur \((y_{\max} - \bar{y})/s\) pour la valeur maximale ou \((\bar{y} - y_{\min})/s\) pour la valeur minimale), il faut remplacer \(\alpha/(2N)\) par \(\alpha/N\).
Écrire une fonction
zscore(y)agissant sur un tableau \(y\) et retournant le score \(z\) pour chaque élément:\[z_{i} = \frac{y_{i} - \bar{y}}{s}\]où \(\bar{y}\) et \(s\) s désignent respectivement la moyenne (
numpy.mean) et l’écart type (numpy.std) de l’échantillon.
Écrire une fonction
grubbs_gmax(n, alpha=0.05, onesided=False)retournant la valeur critique \(G_{\max}(N, \alpha)\) de la statistique de Grubbs pour \(N\) points de données et un niveau de signification \(\alpha\), dans le cas bilatéral (onesided=False) ou unilatéral (True).Utiliser
scipy.stats.t.isf(epsilon, m)pour la valeur critique \(t^{*}_{\epsilon, M}\) de la distribution de Student: \(\int_{t^{*}}^{\infty} t_{m}(x) \text{d}x = \epsilon\).
Écrire une fonction
grubbs_test_twosided(y, alpha=0.05)qui:calcule le score \(z_{i}\) pour chacun des \(N\) points de \(y\),
calcule la valeur critique \(G_{\max}(N, \alpha)\) (cas bilatéral),
calcule la statistique \(G\) (utiliser
numpy.amax),retourne le tableau de booléens
(z == g) & (g > gmax)pour chacun des points.
Un seul de tous les points peut éventuellement passer ce test et être qualifié d’abérrant.
Écrire une fonction
grubbs_test(y, side=0, alpha=0.05)généralisant la fonction précédente aux cas unilatéraux (side=+1pour le test du maximum,-1pour le minimum,side=0pour le test bilatéral). Attention aux cas ``side=±1``.
Écrire une fonction
grubbs_clip(y, side=0, alpha=0.05)retournant le jeu de données \(y\) expurgé de son éventuel point abérrant d’après le test de Grubbs.
Droite de Henry🔗
Le test de Grubbs est basé sur l’hypothèse de normalité: il faut s’assurer que les données (hors points abérrants) sont raisonnablement approximées par une distribution normale pour l’appliquer.
La droite de Henry est une méthode graphique de type « diagramme Quantile-Quantile » pour estimer la normalité d’une série d’observations. Elle compare la distribution observée des quantiles \(o_{i}\) (« ordered response » en ordonnées, càd juste la version ordonnée de \(y\)) à la distribution attendue des quantiles \(z_{i}\) (« order statistics median » en absisses) dans le cas d’une distribution normale, p.ex. (Wikipedia):
où \(\Phi^{-1}\) est la fonction quantile normale (scipy.stats.norm.ppf).
Pour information, cette définition des « rankits » \(q\) est légèrement différente de l’implémentation de scipy.stats.probplot.
Écrire une fonction
normal_quantiles(y)retournant \((z, o)\) définis ci-dessus pour un jeu de données \(y\).
Écrire une fonction graphique
plot_quantiles(y)traçant \(o\) en fonction de \(z\), et y ajoutant la droite de régression linéaire et le coefficient de corrélation linéaire (utiliserscipy.stats.linregress), p.ex.:>>> rng = np.random.default_rng(0) >>> y = rng.normal(size=100) >>> plot_quantiles(y)
Illustrer la pertinence du test de Grubbs sur le jeu de données suivant en traçant les droites de Henry (
plot_quantiles) avant puis après élimination du point abérrant:>>> y = np.array([201.92, 202.18, 200.82, 201.95, 200.19, 245.57, 199.31, 199.53])
Si vous n’avez pas réussi à stocker votre package sous ``git``, envoyer votre notebook à y.copin@ipnl.in2p3.fr.
Packaging🔗
Extraire les fonctions précédentes (
zscore,grubbs_gmax,grubbs_test_twosided,grubbs_test,grubbs_clip,normal_quantilesetplot_quantiles) et les inclure dans un fichiergrubbs.py. Il constituera le module de votre package.Documenter le module et les fonctions par des docstrings (objectif, paramètres, valeur de retour, etc.).
Créer un package
Exam22_Nom_Prenomconstitué du seul modulegrubbs.py, avec l’arborescence suivante:Exam22_Nom_Prenom/ ├── grubbs_nom_prenom │ ├── grubbs.py │ └── __init__.py ├── LICENSE ├── README ├── setup.cfg └── setup.py
avec les fichiers suivants (à adapter à votre contexte):
Ajouter un répertoire
doc/pour configurer et générer la documentation Sphinx du package (voir documentation pyyc). Y inclure votre notebook (sousdoc/notebooks/) dans une section dédiée.Si vous n’avez pas réussi à stocker votre package sous
git, générer un tarball des sources de votre package (duquel vous aurez effacé les répertoires_build/,dist/s’ils existent),$ tar cvzf Exam22_NOM_Prenom.tgz Exam22_NOM_Prenom/
et envoyer le tarball résultant à nouveau à y.copin@ipnl.in2p3.fr.
Tests🔗
Tests unitaires🔗
[2]:
import unittest
class TestNotebook(unittest.TestCase):
def setUp(self):
self.y = np.array([201.92, 202.18, 200.82, 201.95, 200.19, 245.57, 199.31, 199.53])
def test_01_zscore(self):
np.testing.assert_allclose(
zscore(self.y),
[-0.3043925 , -0.28685895, -0.37857289, -0.3023694 ,
-0.42105803, 2.63922038, -0.48040234, -0.46556626])
def test_02_grubbs_gmax(self):
self.assertAlmostEqual(grubbs_gmax(n=8, alpha=0.05, onesided=False),
2.126645087195626)
self.assertAlmostEqual(grubbs_gmax(n=8, alpha=0.05, onesided=True),
2.031652001549952)
def test_03_grubbs_test_twosided(self):
np.testing.assert_equal(grubbs_test_twosided(self.y, alpha=0.05),
[False, False, False, False, False, True, False, False])
def test_04_grubbs_test(self):
np.testing.assert_equal(grubbs_test(self.y, side=0, alpha=0.05),
[False, False, False, False, False, True, False, False])
np.testing.assert_equal(grubbs_test(self.y, side=+1, alpha=0.05),
[False, False, False, False, False, True, False, False])
np.testing.assert_equal(grubbs_test(self.y, side=-1, alpha=0.05),
[False, False, False, False, False, False, False, False])
np.testing.assert_equal(grubbs_test(-self.y, side=-1, alpha=0.05),
[False, False, False, False, False, True, False, False])
def test_05_grubbs_clip(self):
np.testing.assert_allclose(
grubbs_clip(self.y, side=0, alpha=0.05),
[201.92, 202.18, 200.82, 201.95, 200.19, 199.31, 199.53])
def test_06_normal_quantiles(self):
osm, osr = normal_quantiles(self.y)
np.testing.assert_allclose(
osm,
[-1.43420016, -0.85249503, -0.47278912, -0.15250597,
0.15250597, 0.47278912, 0.85249503, 1.43420016])
np.testing.assert_allclose(
osr,
[199.31, 199.53, 200.19, 200.82, 201.92, 201.95, 202.18, 245.57])
unittest.TestLoader.sortTestMethodsUsing = lambda *args: +1
unittest.main(argv=[''], verbosity=2, exit=False)
test_01_zscore (__main__.TestNotebook) ... ERROR
test_02_grubbs_gmax (__main__.TestNotebook) ... ERROR
test_03_grubbs_test_twosided (__main__.TestNotebook) ... ERROR
test_04_grubbs_test (__main__.TestNotebook) ... ERROR
test_05_grubbs_clip (__main__.TestNotebook) ... ERROR
test_06_normal_quantiles (__main__.TestNotebook) ... ERROR
======================================================================
ERROR: test_01_zscore (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_73262/1471779683.py", line 10, in test_01_zscore
zscore(self.y),
NameError: name 'zscore' is not defined
======================================================================
ERROR: test_02_grubbs_gmax (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_73262/1471779683.py", line 15, in test_02_grubbs_gmax
self.assertAlmostEqual(grubbs_gmax(n=8, alpha=0.05, onesided=False),
NameError: name 'grubbs_gmax' is not defined
======================================================================
ERROR: test_03_grubbs_test_twosided (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_73262/1471779683.py", line 21, in test_03_grubbs_test_twosided
np.testing.assert_equal(grubbs_test_twosided(self.y, alpha=0.05),
NameError: name 'grubbs_test_twosided' is not defined
======================================================================
ERROR: test_04_grubbs_test (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_73262/1471779683.py", line 25, in test_04_grubbs_test
np.testing.assert_equal(grubbs_test(self.y, side=0, alpha=0.05),
NameError: name 'grubbs_test' is not defined
======================================================================
ERROR: test_05_grubbs_clip (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_73262/1471779683.py", line 36, in test_05_grubbs_clip
grubbs_clip(self.y, side=0, alpha=0.05),
NameError: name 'grubbs_clip' is not defined
======================================================================
ERROR: test_06_normal_quantiles (__main__.TestNotebook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/ipykernel_73262/1471779683.py", line 40, in test_06_normal_quantiles
osm, osr = normal_quantiles(self.y)
NameError: name 'normal_quantiles' is not defined
----------------------------------------------------------------------
Ran 6 tests in 0.006s
FAILED (errors=6)
<unittest.main.TestProgram object at 0x7ff4d95778b0>
[ ]:
Cette page a été générée à partir de
exam22.ipynb.