Ceci est un document org-mode avec quelques exemples de code
* Préparation des données
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
Les données de l'incidence de la varicelle 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:
| ~indicator~ | Code de l'indicateur de surveillance |
print("Hello world!")
| ~inc~ | Estimation de l'incidence de consultations en nombre de cas |
#+end_src
| ~inc_low~ | Estimation de la borne inférieure de l'IC95% du nombre de cas de consultation |
| ~inc_up~ | Estimation de la borne supérieure de l'IC95% du nombre de cas de consultation |
| ~inc100~ | Estimation du taux d'incidence du nombre de cas de consultation (en cas pour 100,000 habitants) |
| ~inc100_low~ | Estimation de la borne inférieure de l'IC95% du taux d'incidence du nombre de cas de consultation (en cas pour 100,000 habitants) |
| ~inc100_up~ | Estimation de la borne supérieure de l'IC95% du taux d'incidence du nombre de cas de consultation (en cas pour 100,000 habitants) |
| ~geo_insee~ | Code de la zone géographique concernée (Code INSEE) http://www.insee.fr/fr/methodes/nomenclatures/cog/ |
| ~geo_name~ | Libellé de la zone géographique (ce libellé peut être modifié sans préavis) |
L'indication d'une semaine calendaire en format [[https://en.wikipedia.org/wiki/ISO_8601][ISO-8601]] est populaire en Europe, mais peu utilisée aux Etats-Unis. Ceci explique peut-être que peu de logiciels savent gérer ce format. Le langage Python le fait depuis la version 3.6. Nous utilisons donc ce langage pour la préparation de nos données, ce qui a l'avantage de ne nécessiter aucune bibliothèque supplémentaire. (Note: nous expliquerons dans le module 4 pourquoi il est avantageux pour la réproductibilité de se limiter à un minimum de bibliothèques.)
** Téléchargement
Si le fichier de données local existe, on en extrait les données, sinon, on le créé à partir des données téléchargées depuis l'URL.
Après avoir récupéré les données, nous commençons par l'extraction des données qui nous intéressent. D'abord nous découpons le contenu du fichier en lignes, dont nous jetons la première qui ne contient qu'un commentaire. Les autres lignes sont découpées en colonnes.
Besoin de passer :results de "silent" à "output" sinon rien ne marche !
(indiquer ~both~) car l'objectif est que vos analyses de données soient
parfaitement transparentes pour être reproductibles.
** 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.
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
Nous construisons un nouveau jeu de données sans les lignes qui contiennent des champs vides. Nous affichons ces lignes pour en garder une trace.
de le committer si vous voulez que votre analyse soit lisible et
#+BEGIN_SRC python :results output
compréhensible sur GitLab.
valid_table = []
for row in table:
Enfin, n'oubliez pas que nous vous fournissons dans les ressources de
missing = any([column == '' for column in row])
ce MOOC une configuration avec un certain nombre de raccourcis
if missing:
claviers permettant de créer rapidement les blocs de code python (en
print(row)
faisant ~<p~, ~<P~ ou ~<PP~ suivi de ~Tab~).
else:
valid_table.append(row)
Maintenant, à vous de jouer! Vous pouvez effacer toutes ces
#+END_SRC
informations et les remplacer par votre document computationnel.
** 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
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
del inc[0]
data = list(zip(week, inc))
#+END_SRC
Regardons les premières et les dernières lignes. Nous insérons ~None~ pour indiquer à org-mode la séparation entre les trois sections du tableau: en-tête, début des données, fin des données.
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
for week, inc in data:
if len(week) != 6 or not week.isdigit():
print("Valeur suspecte dans la colonne 'week': ", (week, inc))
if not inc.isdigit():
print("Valeur suspecte dans la colonne 'inc': ", (week, inc))
#+END_SRC
Pas de problème !
** Conversions
Pour faciliter les traitements suivants, nous remplaçons les numéros de semaine ISO par les dates qui correspondent aux lundis. A cette occasion, nous trions aussi les données par la date, et nous transformons les incidences en nombres entiers.
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
dates = [date for date, _ in converted_data]
for date1, date2 in zip(dates[:-1], dates[1:]):
if date2-date1 != datetime.timedelta(weeks=1):
print(f"Il y a {date2-date1} entre {date1} et {date2}")
#+END_SRC
** 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.
Nous utilisons le mécanisme d'échange de données proposé par org-mode, ce qui nécessite un peu de code Python pour transformer les données dans le bon format.
#+NAME: data-for-R
#+BEGIN_SRC python :results silent
[('date', 'inc'), None] + [(str(date), inc) for date, inc in converted_data]
#+END_SRC
En R, les données arrivent sous forme d'un data frame, mais il faut encore convertir les dates, qui arrivent comme chaînes de caractères.
#+BEGIN_SRC R :results output :var data=data-for-R
data$date <- as.Date(data$date)
summary(data)
#+END_SRC
** Inspection
Regardons enfin à quoi ressemblent nos données !
#+BEGIN_SRC R :results output graphics :file inc-plot.png
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
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