From 198859076e7598dcaa434b62c485e56a993b59b8 Mon Sep 17 00:00:00 2001 From: Samuel MEYNARD Date: Sat, 6 Jun 2020 17:18:25 +0200 Subject: [PATCH] =?UTF-8?q?D=C3=A9but=20d'=C3=A9tude=20ici=20jusqu'au=20po?= =?UTF-8?q?int=202?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exo1/toy_document_orgmode_python_fr.org | 61 +++++- module2/exo2/exercice_python_en.org | 5 +- module2/exo2/exercice_python_fr.org | 169 ++++++++++------- module2/exo5/exo5_python_fr.org | 2 +- module2/exo5/freq_temp_python.png | Bin 12556 -> 12539 bytes module2/exo5/proba_estimate_python.png | Bin 14660 -> 14547 bytes module3/exo1/analyse-syndrome-grippal.org | 94 ++++++++- module3/exo3/exercice_python_fr.org | 179 +++++++++++------- 8 files changed, 360 insertions(+), 150 deletions(-) diff --git a/module2/exo1/toy_document_orgmode_python_fr.org b/module2/exo1/toy_document_orgmode_python_fr.org index 944b26e..582da9a 100644 --- a/module2/exo1/toy_document_orgmode_python_fr.org +++ b/module2/exo1/toy_document_orgmode_python_fr.org @@ -12,10 +12,65 @@ * En demandant à la lib maths -Mon ordinateur m'indique que π vaut approximativement: -#+begin_src python :results output :exports both -from math import * +Mon ordinateur m'indique que $\pi$ vaut /approximativement/: + +#+begin_src python :results value :session *python* :exports both +from math import pi pi #+end_src #+RESULTS: +: 3.141592653589793 + +* En utilisant la méthode des aiguilles de Buffon + +Mais calculé avec la *méthode* des _aiguilles de Buffon_, on obtiendrait comme *approximation* : + +#+begin_src python :results value :session *python* :exports both +import numpy as np +np.random.seed(seed=42) +N = 10000 +x = np.random.uniform(size=N, low=0, high=1) +theta = np.random.uniform(size=N, low=0, high=pi/2) +2/(sum((x+np.sin(theta))>1)/N) +#+end_src + +#+RESULTS: +: 3.128911138923655 + +* Avec un argument "fréquentiel" de surface +Sinon, une méthode plus simple à comprendre et ne faisant pas intervenir d'appel à la fonction sinus se base sur le fait que si $X∼U(0,1) et Y∼U(0,1) alors P[X2+Y2≤1]=\pi/4$ (voir méthode de Monte Carlo sur Wikipedia). Le code suivant illustre ce fait : + + +#+begin_src python :results output file :var matplot_lib_filename="figure_pi_mc2.png" :exports both :session *python*y +import matplotlib.pyplot as plt + +np.random.seed(seed=42) +N = 1000 +x = np.random.uniform(size=N, low=0, high=1) +y = np.random.uniform(size=N, low=0, high=1) + +accept = (x*x+y*y) <= 1 +reject = np.logical_not(accept) + +fig, ax = plt.subplots(1) +ax.scatter(x[accept], y[accept], c='b', alpha=0.2, edgecolor=None) +ax.scatter(x[reject], y[reject], c='r', alpha=0.2, edgecolor=None) +ax.set_aspect('equal') + +plt.savefig(matplot_lib_filename) +print(matplot_lib_filename) +#+end_src + + +Il est alors aisé d'obtenir une approximation (pas terrible) de $\pi$ en +comptant combien de fois, en moyenne, $X^2 + Y^2$ est inférieur à 1 : + +#+begin_src python :results output :session *python* :exports both +4*np.mean(accept) +#+end_src + +#+RESULTS: +: 3.112 +: +: diff --git a/module2/exo2/exercice_python_en.org b/module2/exo2/exercice_python_en.org index 5782f49..9931d50 100644 --- a/module2/exo2/exercice_python_en.org +++ b/module2/exo2/exercice_python_en.org @@ -60,7 +60,7 @@ print(x) #+end_example Finally, an example for graphical output: -#+begin_src python :results output file :session :var matplot_lib_filename="./cosxsx.png" :exports results +#+begin_src python :results value :session :var matplot_lib_filename="./cosxsx.png" :exports results import matplotlib.pyplot as plt plt.figure(figsize=(10,5)) @@ -72,7 +72,8 @@ print(matplot_lib_filename) #+end_src #+RESULTS: -[[file:./cosxsx.png]] +[[./cosxsx.png]] + Note the parameter ~:exports results~, which indicates that the code will not appear in the exported document. We recommend that in the diff --git a/module2/exo2/exercice_python_fr.org b/module2/exo2/exercice_python_fr.org index c7157ba..aed29a2 100644 --- a/module2/exo2/exercice_python_fr.org +++ b/module2/exo2/exercice_python_fr.org @@ -1,4 +1,4 @@ -#+TITLE: Votre titre +#+TITLE: Exo2 #+AUTHOR: Votre nom #+DATE: La date du jour #+LANGUAGE: fr @@ -11,83 +11,108 @@ #+HTML_HEAD: #+HTML_HEAD: -* Quelques explications - -Ceci est un document org-mode avec quelques exemples de code -python. Une fois ouvert dans emacs, ce document peut aisément être -exporté au format HTML, PDF, et Office. Pour plus de détails sur -org-mode vous pouvez consulter https://orgmode.org/guide/. - -Lorsque vous utiliserez le raccourci =C-c C-e h o=, ce document sera -compilé en html. Tout le code contenu sera ré-exécuté, les résultats -récupérés et inclus dans un document final. Si vous ne souhaitez pas -ré-exécuter tout le code à chaque fois, il vous suffit de supprimer -le # et l'espace qui sont devant le ~#+PROPERTY:~ au début de ce -document. - -Comme nous vous l'avons montré dans la vidéo, on inclue du code -python de la façon suivante (et on l'exécute en faisant ~C-c C-c~): - -#+begin_src python :results output :exports both -print("Hello world!") +* Donnée +#+begin_src python :results value :exports both :session +data = [14.0, 7.6, 11.2, 12.8, 12.5, 9.9, 14.9, 9.4, 16.9, 10.2, 14.9, 18.1, 7.3, 9.8, 10.9,12.2, 9.9, 2.9, 2.8, 15.4, 15.7, 9.7, 13.1, 13.2, 12.3, 11.7, 16.0, 12.4, 17.9, 12.2, 16.2, 18.7, 8.9, 11.9, 12.1, 14.6, 12.1, 4.7, 3.9, 16.9, 16.8, 11.3, 14.4, 15.7, 14.0, 13.6, 18.0, 13.6, 19.9, 13.7, 17.0, 20.5, 9.9, 12.5, 13.2, 16.1, 13.5, 6.3, 6.4, 17.6, 19.1, 12.8, 15.5, 16.3, 15.2, 14.6, 19.1, 14.4, 21.4, 15.1, 19.6, 21.7, 11.3, 15.0, 14.3, 16.8, 14.0, 6.8, 8.2, 19.9, 20.4, 14.6, 16.4, 18.7, 16.8, 15.8, 20.4, 15.8, 22.4, 16.2, 20.3, 23.4, 12.1, 15.5, 15.4, 18.4, 15.7, 10.2, 8.9, 21.0] +data #+end_src #+RESULTS: -: Hello world! +| 14.0 | 7.6 | 11.2 | 12.8 | 12.5 | 9.9 | 14.9 | 9.4 | 16.9 | 10.2 | 14.9 | 18.1 | 7.3 | 9.8 | 10.9 | 12.2 | 9.9 | 2.9 | 2.8 | 15.4 | 15.7 | 9.7 | 13.1 | 13.2 | 12.3 | 11.7 | 16.0 | 12.4 | 17.9 | 12.2 | 16.2 | 18.7 | 8.9 | 11.9 | 12.1 | 14.6 | 12.1 | 4.7 | 3.9 | 16.9 | 16.8 | 11.3 | 14.4 | 15.7 | 14.0 | 13.6 | 18.0 | 13.6 | 19.9 | 13.7 | 17.0 | 20.5 | 9.9 | 12.5 | 13.2 | 16.1 | 13.5 | 6.3 | 6.4 | 17.6 | 19.1 | 12.8 | 15.5 | 16.3 | 15.2 | 14.6 | 19.1 | 14.4 | 21.4 | 15.1 | 19.6 | 21.7 | 11.3 | 15.0 | 14.3 | 16.8 | 14.0 | 6.8 | 8.2 | 19.9 | 20.4 | 14.6 | 16.4 | 18.7 | 16.8 | 15.8 | 20.4 | 15.8 | 22.4 | 16.2 | 20.3 | 23.4 | 12.1 | 15.5 | 15.4 | 18.4 | 15.7 | 10.2 | 8.9 | 21.0 | -Voici la même chose, mais avec une session python, donc une -persistance d'un bloc à l'autre (et on l'exécute toujours en faisant -~C-c C-c~). -#+begin_src python :results output :session :exports both -import numpy -x=numpy.linspace(-15,15) -print(x) +#+begin_src python :results value :session :var matplot_lib_filename="fig1.png" :exports both +from numpy import mean, min, max, median, std +import matplotlib +import matplotlib.pyplot as plt +d_mean = mean(data) +d_min = min(data) +d_max = max(data) +d_median = median(data) +d_std = std(data, ddof=1) +f"Mean : {d_mean}\nMin: {d_min}\nMax: {d_max}\nMediane: {d_median}\nEcart Type: {d_std}" #+end_src #+RESULTS: -#+begin_example -[-15. -14.3877551 -13.7755102 -13.16326531 -12.55102041 - -11.93877551 -11.32653061 -10.71428571 -10.10204082 -9.48979592 - -8.87755102 -8.26530612 -7.65306122 -7.04081633 -6.42857143 - -5.81632653 -5.20408163 -4.59183673 -3.97959184 -3.36734694 - -2.75510204 -2.14285714 -1.53061224 -0.91836735 -0.30612245 - 0.30612245 0.91836735 1.53061224 2.14285714 2.75510204 - 3.36734694 3.97959184 4.59183673 5.20408163 5.81632653 - 6.42857143 7.04081633 7.65306122 8.26530612 8.87755102 - 9.48979592 10.10204082 10.71428571 11.32653061 11.93877551 - 12.55102041 13.16326531 13.7755102 14.3877551 15. ] -#+end_example - -Et enfin, voici un exemple de sortie graphique: -#+begin_src python :results output file :session :var matplot_lib_filename="./cosxsx.png" :exports results +: Mean : 14.113000000000001 +: Min: 2.8 +: Max: 23.4 +: Mediane: 14.5 +: Ecart Type: 4.334094455301447 + +#+BEGIN_SRC python :session :results file +import matplotlib import matplotlib.pyplot as plt - -plt.figure(figsize=(10,5)) -plt.plot(x,numpy.cos(x)/x) -plt.tight_layout() - -plt.savefig(matplot_lib_filename) -print(matplot_lib_filename) -#+end_src - +fig=plt.figure(figsize=(3,2)) +plt.hist(data) +plt.savefig('test.png') +'./test.png' +#+END_SRC #+RESULTS: -[[file:./cosxsx.png]] - -Vous remarquerez le paramètre ~:exports results~ qui indique que le code -ne doit pas apparaître dans la version finale du document. Nous vous -recommandons dans le cadre de ce MOOC de ne pas changer ce paramètre -(indiquer ~both~) car l'objectif est que vos analyses de données soient -parfaitement transparentes pour être reproductibles. - -Attention, la figure ainsi générée n'est pas stockée dans le document -org. C'est un fichier ordinaire, ici nommé ~cosxsx.png~. N'oubliez pas -de le committer si vous voulez que votre analyse soit lisible et -compréhensible sur GitLab. - -Enfin, n'oubliez pas que nous vous fournissons dans les ressources de -ce MOOC une configuration avec un certain nombre de raccourcis -claviers permettant de créer rapidement les blocs de code python (en -faisant ~", line 7, in + File "", line 4, in + File "/Library/Python/3.7/site-packages/matplotlib/pyplot.py", line 2610, in hist + if data is not None else {}), **kwargs) + File "/Library/Python/3.7/site-packages/matplotlib/__init__.py", line 1565, in inner + return func(ax, *map(sanitize_sequence, args), **kwargs) + File "/Library/Python/3.7/site-packages/matplotlib/axes/_axes.py", line 6559, in hist + cbook._check_in_list(['left', 'mid', 'right'], align=align) + File "/Library/Python/3.7/site-packages/matplotlib/cbook/__init__.py", line 2145, in _check_in_list + .format(v, k, ', '.join(map(repr, values)))) +ValueError: 'edge' is not a valid value for align; supported values are 'left', 'mid', 'right' +]] +[[file:Traceback (most recent call last): + File "", line 7, in + File "", line 4, in + File "/Library/Python/3.7/site-packages/matplotlib/pyplot.py", line 2610, in hist + if data is not None else {}), **kwargs) + File "/Library/Python/3.7/site-packages/matplotlib/__init__.py", line 1565, in inner + return func(ax, *map(sanitize_sequence, args), **kwargs) + File "/Library/Python/3.7/site-packages/matplotlib/axes/_axes.py", line 6559, in hist + cbook._check_in_list(['left', 'mid', 'right'], align=align) + File "/Library/Python/3.7/site-packages/matplotlib/cbook/__init__.py", line 2145, in _check_in_list + .format(v, k, ', '.join(map(repr, values)))) +ValueError: 'edge' is not a valid value for align; supported values are 'left', 'mid', 'right' +]] + File "", line 7, in + File "", line 2, in +ModuleNotFoundError: No module named 'hist' +]] + File "", line 7, in + File "", line 4, in +TypeError: bar() missing 1 required positional argument: 'height' +]] + File "", line 7, in + File "", line 4, in +TypeError: bar() missing 1 required positional argument: 'height' +]] + File "", line 7, in + File "", line 4, in +TypeError: bar() missing 1 required positional argument: 'height' +]] + File "", line 7, in + File "", line 4, in +TypeError: bar() missing 1 required positional argument: 'height' +]] + File "", line 7, in + File "", line 3, in +TypeError: bar() missing 1 required positional argument: 'height' +]] + File "", line 7, in + File "", line 3, in +TypeError: ba .r() missing 1 required positional argument: 'height' +]] + File "", line 7, in + File "", line 3, in +TypeError: bar() missing 1 required positional argument: 'height' +]] + File "", line 7, in + File "", line 3, in +NameError: name 'data' is not defined +]] + File "", line 7, in + File "", line 1, in +NameError: name 'plt' is not defined +]] +[[file:./test.png]] diff --git a/module2/exo5/exo5_python_fr.org b/module2/exo5/exo5_python_fr.org index afff5e0..588159d 100644 --- a/module2/exo5/exo5_python_fr.org +++ b/module2/exo5/exo5_python_fr.org @@ -171,7 +171,7 @@ La température prévue le jour du décollage est de 31°F. Essayons d'estimer la probabilité de dysfonctionnement des joints toriques à cette température à partir du modèle que nous venons de construire: -#+begin_src python :results output file :var matplot_lib_filename="proba_estimate_python.png" :exports both :session *python* +#+begin_src python :results output file :var matplot_lib_filename="proba_estimate_python.png" :exports both :session *python* import matplotlib.pyplot as plt data_pred = pd.DataFrame({'Temperature': np.linspace(start=30, stop=90, num=121), 'Intercept': 1}) diff --git a/module2/exo5/freq_temp_python.png b/module2/exo5/freq_temp_python.png index 93cb9e626441d23f6dff59ed252d7b14eb37abdb..60368ff57389cd4cfc5aa439d8dd53685bb9fe79 100644 GIT binary patch literal 12539 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 literal 12556 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 diff --git a/module2/exo5/proba_estimate_python.png b/module2/exo5/proba_estimate_python.png index 77fc4b275dd8815b1ab91cd3b67b1beb93e00748..046603e2dde7c4ad7cff92729121c427f3b5e393 100644 GIT binary patch literal 14547 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 literal 14660 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 diff --git a/module3/exo1/analyse-syndrome-grippal.org b/module3/exo1/analyse-syndrome-grippal.org index 1720b70..6430b78 100644 --- a/module3/exo1/analyse-syndrome-grippal.org +++ b/module3/exo1/analyse-syndrome-grippal.org @@ -27,11 +27,18 @@ if sys.version_info.major < 3 or sys.version_info.minor < 6: print("Veuillez utiliser Python 3.6 (ou plus) !") #+END_SRC +#+RESULTS: +: Python 3.8.2 (default, Mar 11 2020, 00:29:50) +: [Clang 11.0.0 (clang-1100.0.33.17)] on darwin +: Type "help", "copyright", "credits" or "license" for more information. + #+BEGIN_SRC emacs-lisp :results output (unless (featurep 'ob-python) (print "Veuillez activer python dans org-babel (org-babel-do-languages) !")) #+END_SRC +#+RESULTS: + ** R 3.4 Nous n'utilisons que des fonctionnalités de base du langage R, une version antérieure devrait suffire. @@ -40,6 +47,14 @@ Nous n'utilisons que des fonctionnalités de base du langage R, une version ant (print "Veuillez activer R dans org-babel (org-babel-do-languages) !")) #+END_SRC +#+RESULTS: + +#+begin_src R :results output graphics :file (org-babel-temp-file "figure" ".png") :exports both :width 600 :height 400 :session *R* +test +#+end_src + +#+RESULTS: + * Préparation des données Les données de l'incidence du syndrome grippal sont disponibles du site Web du [[http://www.sentiweb.fr/][Réseau Sentinelles]]. Nous les récupérons sous forme d'un fichier en format CSV dont chaque ligne correspond à une semaine de la période d'observation. Nous téléchargeons toujours le jeu de données complet (rien d'autre n'est proposé), qui commence en 1984 et se termine avec une semaine récente. L'URL est: @@ -80,6 +95,13 @@ Regardons ce que nous avons obtenu: table[:5] #+END_SRC +#+RESULTS: +| week | indicator | inc | inc_low | inc_up | inc100 | inc100_low | inc100_up | geo_insee | geo_name | +| 202011 | 3 | 101704 | 93652 | 109756 | 154 | 142 | 166 | FR | France | +| 202010 | 3 | 104977 | 96650 | 113304 | 159 | 146 | 172 | FR | France | +| 202009 | 3 | 110696 | 102066 | 119326 | 168 | 155 | 181 | FR | France | +| 202008 | 3 | 143753 | 133984 | 153522 | 218 | 203 | 233 | FR | France | + ** Recherche de données manquantes Il y a malheureusement beaucoup de façon d'indiquer l'absence d'un point de données. Nous testons ici seulement pour la présence de champs vides. Il faudrait aussi rechercher des valeurs non-numériques dans les colonnes à priori numériques. Nous ne le faisons pas ici, mais une vérification ultérieure capterait des telles anomalies. @@ -94,6 +116,9 @@ for row in table: valid_table.append(row) #+END_SRC +#+RESULTS: +: ['198919', '3', '0', '', '', '0', '', '', 'FR', 'France'] + ** Extraction des colonnes utilisées Il y a deux colonnes qui nous intéressent: la première (~"week"~) et la troisième (~"inc"~). Nous vérifions leurs noms dans l'en-tête, que nous effaçons par la suite. Enfin, nous créons un tableau avec les deux colonnes pour le traitement suivant. #+BEGIN_SRC python :results silent @@ -101,7 +126,7 @@ week = [row[0] for row in valid_table] assert week[0] == 'week' del week[0] inc = [row[2] for row in valid_table] -assert inc[0] == 'inc +assert inc[0] == 'inc' del inc[0] data = list(zip(week, inc)) #+END_SRC @@ -111,6 +136,21 @@ Regardons les premières et les dernières lignes. Nous insérons ~None~ pour in [('week', 'inc'), None] + data[:5] + [None] + data[-5:] #+END_SRC +#+RESULTS: +| week | inc | +|--------+--------| +| 202011 | 101704 | +| 202010 | 104977 | +| 202009 | 110696 | +| 202008 | 143753 | +| 202007 | 183610 | +|--------+--------| +| 198448 | 78620 | +| 198447 | 72029 | +| 198446 | 87330 | +| 198445 | 135223 | +| 198444 | 68422 | + ** Vérification Il est toujours prudent de vérifier si les données semblent crédibles. Nous savons que les semaines sont données par six chiffres (quatre pour l'année et deux pour la semaine), et que les incidences sont des nombres entiers positifs. #+BEGIN_SRC python :results output @@ -121,6 +161,8 @@ for week, inc in data: print("Valeur suspecte dans la colonne 'inc': ", (week, inc)) #+END_SRC +#+RESULTS: + Pas de problème ! ** Conversions @@ -140,6 +182,21 @@ str_data = [(str(date), str(inc)) for date, inc in converted_data] [('date', 'inc'), None] + str_data[:5] + [None] + str_data[-5:] #+END_SRC +#+RESULTS: +| date | inc | +|------------+--------| +| 1984-10-29 | 68422 | +| 1984-11-05 | 135223 | +| 1984-11-12 | 87330 | +| 1984-11-19 | 72029 | +| 1984-11-26 | 78620 | +|------------+--------| +| 2020-02-10 | 183610 | +| 2020-02-17 | 143753 | +| 2020-02-24 | 110696 | +| 2020-03-02 | 104977 | +| 2020-03-09 | 101704 | + ** Vérification des dates Nous faisons encore une vérification: nos dates doivent être séparées d'exactement une semaine, sauf autour du point manquant. #+BEGIN_SRC python :results output @@ -149,6 +206,9 @@ for date1, date2 in zip(dates[:-1], dates[1:]): print(f"Il y a {date2-date1} entre {date1} et {date2}") #+END_SRC +#+RESULTS: +: Il y a 14 days, 0:00:00 entre 1989-05-01 et 1989-05-15 + ** Passage Python -> R Nous passons au langage R pour inspecter nos données, parce que l'analyse et la préparation de graphiques sont plus concises en R, sans nécessiter aucune bibliothèque supplémentaire. @@ -164,17 +224,30 @@ data$date <- as.Date(data$date) summary(data) #+END_SRC +#+RESULTS: +: +: date inc +: Min. :1984-10-29 Min. : 0 +: 1st Qu.:1993-09-06 1st Qu.: 5018 +: Median :2002-07-08 Median : 16002 +: Mean :2002-07-07 Mean : 62071 +: 3rd Qu.:2011-05-09 3rd Qu.: 50759 +: Max. :2020-03-09 Max. :1001824 + ** Inspection Regardons enfin à quoi ressemblent nos données ! -#+BEGIN_SRC R :results output graphics :file inc-plot.png + +< plot(data, type="l", xlab="Date", ylab="Incidence hebdomadaire") -#+END_SRC + Un zoom sur les dernières années montre mieux la situation des pics en hiver. Le creux des incidences se trouve en été. #+BEGIN_SRC R :results output graphics :file inc-plot-zoom.png plot(tail(data, 200), type="l", xlab="Date", ylab="Incidence hebdomadaire") #+END_SRC +#+RESULTS: + * Étude de l'incidence annuelle ** Calcul de l'incidence annuelle @@ -201,6 +274,9 @@ inc_annuelle = data.frame(annee = annees, head(inc_annuelle) #+END_SRC +#+RESULTS: +: org_babel_R_eoe + ** Inspection Voici les incidences annuelles en graphique. #+BEGIN_SRC R :results output graphics :file annual-inc-plot.png @@ -213,7 +289,19 @@ Une liste triée par ordre décroissant d'incidence annuelle permet de plus faci head(inc_annuelle[order(-inc_annuelle$incidence),]) #+END_SRC +#+RESULTS: +: Error in head(inc_annuelle[order(-inc_annuelle$incidence), ]) : +: objet 'inc_annuelle' introuvable + Enfin, un histogramme montre bien que les épidémies fortes, qui touchent environ 10% de la population française, sont assez rares: il y en eu trois au cours des 35 dernières années. #+BEGIN_SRC R :results output graphics :file annual-inc-hist.png hist(inc_annuelle$incidence, breaks=10, xlab="Incidence annuelle", ylab="Nb d'observations", main="") #+END_SRC + + +#+NAME: test +#+BEGIN_SRC R :file "test1.png" :results output graphics silent +x <- seq(-pi, pi, 0.1) +plot(x, sin(x)) +#+END_SRC +[[file:test.svg]] diff --git a/module3/exo3/exercice_python_fr.org b/module3/exo3/exercice_python_fr.org index c7157ba..3343e8c 100644 --- a/module3/exo3/exercice_python_fr.org +++ b/module3/exo3/exercice_python_fr.org @@ -1,6 +1,6 @@ -#+TITLE: Votre titre -#+AUTHOR: Votre nom -#+DATE: La date du jour +#+TITLE: Sujet 4 : Estimation de la latence et de la capacité d’une connexion à partir de mesures asymétriques +#+AUTHOR: Samuel MEYNARD +#+DATE: <2020-06-06 Sat> #+LANGUAGE: fr # #+PROPERTY: header-args :eval never-export @@ -11,83 +11,124 @@ #+HTML_HEAD: #+HTML_HEAD: -* Quelques explications +* Énoncé +Un modèle simple et fréquemment utilisé pour décrire la performance d'une connexion de réseau consiste à supposer que le temps d'envoi T pour un message dépend principalement de sa taille $S$ (nombre d'octets) et de deux grandeurs propres à la connexion : la latence $L$ (en secondes) et la capacité $C$ (en octets/seconde). La relation entre ces quatre quantités est $T(S) = L + S/C$. Ce modèle néglige un grand nombre de détails. D'une part, $L$ et $C$ dépendent bien sûr du protocole de communication choisi mais aussi dans une certaine mesure de $S$. D'autre part, la mesure de $T(S)$ comporte en général une forte composante aléatoire. Nous nous intéressons ici au temps moyen qu'il faut pour envoyer un message d'une taille donnée. -Ceci est un document org-mode avec quelques exemples de code -python. Une fois ouvert dans emacs, ce document peut aisément être -exporté au format HTML, PDF, et Office. Pour plus de détails sur -org-mode vous pouvez consulter https://orgmode.org/guide/. +Votre tâche est d'estimer $L$ et $C$ à partir d'une série d'observations de $T$ pour des valeurs différentes de $S$. Préparez votre analyse sous forme d'un document computationnel réplicable qui commence avec la lectures des données brutes, disponibles pour deux connexions différentes, qui ont été obtenues avec l'outil ping : +- Le premier jeu de données examine une connexion courte à l'intérieur d'un campus : http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/liglab2.log.gz +- Le deuxième jeu de données mesure la performance d'une connexion vers un site Web éloigné assez populaire et donc chargé : http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/stackoverflow.log.gz -Lorsque vous utiliserez le raccourci =C-c C-e h o=, ce document sera -compilé en html. Tout le code contenu sera ré-exécuté, les résultats -récupérés et inclus dans un document final. Si vous ne souhaitez pas -ré-exécuter tout le code à chaque fois, il vous suffit de supprimer -le # et l'espace qui sont devant le ~#+PROPERTY:~ au début de ce -document. -Comme nous vous l'avons montré dans la vidéo, on inclue du code -python de la façon suivante (et on l'exécute en faisant ~C-c C-c~): +Les deux fichiers contiennent la sortie brute de l'outil ping qui a été exécuté dans une boucle en variant de façon aléatoire la taille du message. Chaque ligne a la forme suivante: -#+begin_src python :results output :exports both -print("Hello world!") -#+end_src +#+BEGIN_SRC +[1421761682.052172] 665 bytes from lig-publig.imag.fr (129.88.11.7): icmp_seq=1 ttl=60 time=22.5 ms +#+END_SRC + +Au début, entre crochet, vous trouvez la date à laquelle la mesure a été prise, exprimée en secondes depuis le 1er janvier 1970. La taille du message en octets est donnée juste après, suivie par le nom de la machine cible et son adresse IP, qui sont normalement identiques pour toutes les lignes à l'intérieur d'un jeu de données. À la fin de la ligne, nous trouvons le temps d'envoi (aller-retour) en millisecondes. Les autres indications, =icmp_seq= et =ttl=, n'ont pas d'importance pour notre analyse. Attention, il peut arriver qu'une ligne soit incomplète et il faut donc vérifier chaque ligne avant d'en extraire des informations ! + +_Votre mission si vous l'acceptez :_ + +1. Commencez par travailler avec le premier jeu de données (liglab2). Représentez graphiquement l'évolution du temps de transmission au cours du temps (éventuellement à différents instants et différentes échelles de temps) pour évaluer la stabilité temporelle du phénomène. Ces variations peuvent-elles être expliquées seulement par la taille des messages ? +2. Représentez le temps de transmission en fonction de la taille des messages. Vous devriez observer une "rupture", une taille à partir de laquelle la nature de la variabilité change. Vous estimerez (graphiquement) cette taille afin de traiter les deux classes de tailles de message séparément. +3. Effectuez une régression linéaire pour chacune des deux classes et évaluez les valeurs de L et de C correspondantes. Vous superposerez le résultat de cette régression linéaire au graphe précédent. +4. (Optionnel) La variabilité est tellement forte et asymétrique que la régression du temps moyen peut être considérée comme peu pertinente. On peut vouloir s'intéresser à caractériser plutôt le plus petit temps de transmission. Une approche possible consiste donc à filtrer le plus petit temps de transmission pour chaque taille de message et à effectuer la régression sur ce sous-ensemble de données. Cela peut également être l'occasion pour ceux qui le souhaitent de se familiariser avec la régression de quantiles (implémentée en R dans la bibliothèque quantreg et en Python dans la bibliothèque statsmodels). +5. Répétez les étapes précédentes avec le second jeu de données (stackoverflow) +6. Déposer dans FUN votre résultat + +* Récupération du 1^er jeu de donnée +** Téléchargement +#+BEGIN_SRC python :session :file step1.txt :results file +from urllib.request import urlretrieve +from os import path +liglab_file = "liglab2.log" +liglab_filegz = liglab_file + ".gz" +url = "http://mescal.imag.fr/membres/arnaud.legrand/teaching/2014/RICM4_EP_ping/liglab2.log.gz" +if not path.exists(liglab_file): + urlretrieve(url, liglab_filegz) +#+END_SRC #+RESULTS: -: Hello world! +[[file:step1.txt]] +** Lecture du fichier +#+BEGIN_SRC python :session :results output +import gzip +f = gzip.open(liglab_filegz) +data = f.read().decode('latin-1').strip().splitlines() +f.close() +#+END_SRC -Voici la même chose, mais avec une session python, donc une -persistance d'un bloc à l'autre (et on l'exécute toujours en faisant -~C-c C-c~). -#+begin_src python :results output :session :exports both -import numpy -x=numpy.linspace(-15,15) -print(x) -#+end_src +#+RESULTS: + +#+BEGIN_SRC python :session :results replace +table = [row.split(' ') for row in data] +cleantable = [] +for row in table: + if len(row) == 10: + cleantable.append(row) +cleantable[:4] +#+END_SRC + +#+RESULTS: +| [1421761682.052172] | 665 | bytes | from | lig-publig.imag.fr | (129.88.11.7): | icmp_seq=1 | ttl=60 | time=22.5 | ms | +| [1421761682.277315] | 1373 | bytes | from | lig-publig.imag.fr | (129.88.11.7): | icmp_seq=1 | ttl=60 | time=21.2 | ms | +| [1421761682.502054] | 262 | bytes | from | lig-publig.imag.fr | (129.88.11.7): | icmp_seq=1 | ttl=60 | time=21.2 | ms | +| [1421761682.729257] | 1107 | bytes | from | lig-publig.imag.fr | (129.88.11.7): | icmp_seq=1 | ttl=60 | time=23.3 | ms | + +#+BEGIN_SRC python :session :results output replace +from datetime import datetime +date = [datetime.utcfromtimestamp(float(row[0][1:-1])) for row in cleantable] +donnee = [int(row[1]) for row in cleantable] +source = [str(row[4]) for row in cleantable] +ip = [str(row[5][1:-1]) for row in cleantable] +ltime = [float(row[8].split('=')[1]) for row in cleantable] + +dataset = list(zip(date,donnee, ltime)) +print(dataset[:4]) +#+END_SRC #+RESULTS: -#+begin_example -[-15. -14.3877551 -13.7755102 -13.16326531 -12.55102041 - -11.93877551 -11.32653061 -10.71428571 -10.10204082 -9.48979592 - -8.87755102 -8.26530612 -7.65306122 -7.04081633 -6.42857143 - -5.81632653 -5.20408163 -4.59183673 -3.97959184 -3.36734694 - -2.75510204 -2.14285714 -1.53061224 -0.91836735 -0.30612245 - 0.30612245 0.91836735 1.53061224 2.14285714 2.75510204 - 3.36734694 3.97959184 4.59183673 5.20408163 5.81632653 - 6.42857143 7.04081633 7.65306122 8.26530612 8.87755102 - 9.48979592 10.10204082 10.71428571 11.32653061 11.93877551 - 12.55102041 13.16326531 13.7755102 14.3877551 15. ] -#+end_example - -Et enfin, voici un exemple de sortie graphique: -#+begin_src python :results output file :session :var matplot_lib_filename="./cosxsx.png" :exports results +: [(datetime.datetime(2015, 1, 20, 13, 48, 2, 52172), 665, 22.5), (datetime.datetime(2015, 1, 20, 13, 48, 2, 277315), 1373, 21.2), (datetime.datetime(2015, 1, 20, 13, 48, 2, 502054), 262, 21.2), (datetime.datetime(2015, 1, 20, 13, 48, 2, 729257), 1107, 23.3)] + +#+BEGIN_SRC python :session :results silent :file test.png +import matplotlib import matplotlib.pyplot as plt +# Create figure and plot space +fig, ax = plt.subplots(figsize=(12, 12)) + +# Add x-axis and y-axis +ax.scatter(date, + ltime, + color='purple') -plt.figure(figsize=(10,5)) -plt.plot(x,numpy.cos(x)/x) -plt.tight_layout() +# Set title and labels for axes +ax.set(xlabel="Date", + ylabel="Latence", + title="Evolution de la latence dans le temps") -plt.savefig(matplot_lib_filename) -print(matplot_lib_filename) -#+end_src +plt.savefig('test.png') +#+END_SRC #+RESULTS: -[[file:./cosxsx.png]] - -Vous remarquerez le paramètre ~:exports results~ qui indique que le code -ne doit pas apparaître dans la version finale du document. Nous vous -recommandons dans le cadre de ce MOOC de ne pas changer ce paramètre -(indiquer ~both~) car l'objectif est que vos analyses de données soient -parfaitement transparentes pour être reproductibles. - -Attention, la figure ainsi générée n'est pas stockée dans le document -org. C'est un fichier ordinaire, ici nommé ~cosxsx.png~. N'oubliez pas -de le committer si vous voulez que votre analyse soit lisible et -compréhensible sur GitLab. - -Enfin, n'oubliez pas que nous vous fournissons dans les ressources de -ce MOOC une configuration avec un certain nombre de raccourcis -claviers permettant de créer rapidement les blocs de code python (en -faisant ~