diff --git a/module2/exo3/exercice_fr.Rmd b/module2/exo3/exercice_fr.Rmd index 7eece5e296bb586e88166aa8a263ca75b44c2b9e..043fa224cc75a7f770a98bf208a3f1500bd3b212 100644 --- a/module2/exo3/exercice_fr.Rmd +++ b/module2/exo3/exercice_fr.Rmd @@ -1,7 +1,7 @@ --- -title: "Votre titre" -author: "Votre nom" -date: "La date du jour" +title: "Module 2 - exercice 2" +author: "Fanny Mathiaux" +date: "02.06.2026" output: html_document --- @@ -10,24 +10,20 @@ output: html_document knitr::opts_chunk$set(echo = TRUE) ``` -## Quelques explications +Données -Ceci est un document R markdown que vous pouvez aisément exporter au format HTML, PDF, et MS Word. Pour plus de détails sur R Markdown consultez . - -Lorsque vous cliquerez sur le bouton **Knit** ce document sera compilé afin de ré-exécuter le code R et d'inclure les résultats dans un document final. Comme nous vous l'avons montré dans la vidéo, on inclue du code R de la façon suivante: - -```{r cars} -summary(cars) +```{r} +data <- c(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) ``` -Et on peut aussi aisément inclure des figures. Par exemple: +Séquence plot -```{r pressure, echo=FALSE} -plot(pressure) +```{r} +plot(data, type="l") ``` -Vous remarquerez le paramètre `echo = FALSE` 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 utiliser ce paramètre car l'objectif est que vos analyses de données soient parfaitement transparentes pour être reproductibles. - -Comme les résultats ne sont pas stockés dans les fichiers Rmd, pour faciliter la relecture de vos analyses par d'autres personnes, vous aurez donc intérêt à générer un HTML ou un PDF et à le commiter. +Histogram plot -Maintenant, à vous de jouer! Vous pouvez effacer toutes ces informations et les remplacer par votre document computationnel. +```{r} +hist(data) +``` \ No newline at end of file diff --git a/module3/exo1/analyse-syndrome-grippal.Rmd b/module3/exo1/analyse-syndrome-grippal.Rmd index 771e78faac371f23c921f7f7aecc87f2100e9059..f6b0d519f40be48ecbae764dc25a5af3d97a2f3a 100644 --- a/module3/exo1/analyse-syndrome-grippal.Rmd +++ b/module3/exo1/analyse-syndrome-grippal.Rmd @@ -41,10 +41,32 @@ Voici l'explication des colonnes donnée sur le [sur le site d'origine](https:// | `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) | +Pour nous protéger contre une éventuelle disparition ou modification du serveur du Réseau Sentinelles, nous faisons une copie locale de ce jeux de données que nous préservons avec notre analyse. Il est inutile et même risquée de télécharger les données à chaque exécution, car dans le cas d'une panne nous pourrions remplacer nos données par un fichier défectueux. Pour cette raison, nous téléchargeons les données seulement si la copie locale n'existe pas. + +```{r} +data_file = "syndrome-grippal.csv" + +if (!file.exists(data_file)) { + download.file(data_url, data_file, method="auto") +} +# +# files <- list.files() +# dataset <- "dataset_incidence.csv" +# +# if (length(which(grepl(dataset, files) == TRUE)) == 1){ +# data = read.csv(dataset, skip=1) +# } else { +# data = read.csv(data_url, skip=1) +# write.csv(data, dataset) +# } +``` + + + La première ligne du fichier CSV est un commentaire, que nous ignorons en précisant `skip=1`. -### Téléchargement +### Lecture ```{r} -data = read.csv(data_url, skip=1) +data = read.csv(data_file, skip=1) ``` Regardons ce que nous avons obtenu: @@ -64,8 +86,17 @@ Les deux colonnes qui nous intéressent sont `week` et `inc`. Vérifions leurs c class(data$week) class(data$inc) ``` + +On remarque que $$data$inc$$ est un $character$, il faut changer cela : + +```{r} +data$inc <- as.numeric(data$inc) +class(data$inc) +``` + Ce sont des entiers, tout va bien ! + ### Conversion des numéros de semaine La gestion des dates est toujours un sujet délicat. Il y a un grand nombre de conventions différentes qu'il ne faut pas confondre. Notre jeux de données utilise un format que peu de logiciels savent traiter: les semaines en format [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601). En `R`, il est géré par la bibliothèque [parsedate](https://cran.r-project.org/package=parsedate): @@ -74,6 +105,22 @@ La gestion des dates est toujours un sujet délicat. Il y a un grand nombre de c library(parsedate) ``` +Test sur une date exemple : + +```{r} +date <- 199501 +ws <- paste(date) # conversion en chaîne de caractère + +# On va insérer "-W" entre l'année (ici 1995) et la semaine (01) +iso <- paste0(substring(ws, 1, 4), "-W", substring(ws, 5, 6)) +iso + +# Et la fonction suivante permet de convertir le tout en date : +parse_iso_8601(iso) +``` + +Ce traitement est ensuite appliqué à l'ensemble du jeu de données en créant une fonction. + Pour faciliter le traitement suivant, nous remplaçons ces semaines par les dates qui correspondent aux lundis. Voici une petite fonction qui fait la conversion pour une seule valeur: ```{r} @@ -94,7 +141,7 @@ Vérifions qu'elle est de classe `Date`: class(data$date) ``` -Les points sont dans l'ordre chronologique inverse, il est donc utile de les trier: +Les points sont dans l'ordre chronologique inverse, il est donc utile de les trier dans l'ordre chronologique : ```{r} data = data[order(data$date),] ``` @@ -122,6 +169,20 @@ with(tail(data, 200), plot(date, inc, type="l", xlab="Date", ylab="Incidence heb Étant donné que le pic de l'épidémie se situe en hiver, à cheval entre deux années civiles, nous définissons la période de référence entre deux minima de l'incidence, du 1er août de l'année $N$ au 1er août de l'année $N+1$. Nous mettons l'année $N+1$ comme étiquette sur cette année décalée, car le pic de l'épidémie est toujours au début de l'année $N+1$. Comme l'incidence de syndrome grippal est très faible en été, cette modification ne risque pas de fausser nos conclusions. L'argument `na.rm=True` dans la sommation précise qu'il faut supprimer les points manquants. Ce choix est raisonnable car il n'y a qu'un seul point manquant, dont l'impact ne peut pas être très fort. + +Par exemple, faisons cela sur l'année 1990 : +```{r} +annee <- 1990 +debut <- paste0(annee-1, "-08-01") # on ajoute le 1er août à la date +fin <- paste0(annee, "-08-01") # idem + +# Les semaines à sommer sont donc : +semaines <- data$date > debut & data$date <= fin +sum(data$inc[semaines], na.rm=TRUE) +``` + + + ```{r} pic_annuel = function(annee) { debut = paste0(annee-1,"-08-01") diff --git a/module3/exo2/exercice_fr.Rmd b/module3/exo2/exercice_fr.Rmd index 7eece5e296bb586e88166aa8a263ca75b44c2b9e..e76eacc814b94f6c702da4be7b11e9f67291653a 100644 --- a/module3/exo2/exercice_fr.Rmd +++ b/module3/exo2/exercice_fr.Rmd @@ -1,7 +1,7 @@ --- -title: "Votre titre" -author: "Votre nom" -date: "La date du jour" +title: "Analyse de l'incidence de la varicelle" +author: "Fanny Mathiaux" +date: "24.08.2026" output: html_document --- @@ -10,24 +10,166 @@ output: html_document knitr::opts_chunk$set(echo = TRUE) ``` -## Quelques explications +## Préparation des données -Ceci est un document R markdown que vous pouvez aisément exporter au format HTML, PDF, et MS Word. Pour plus de détails sur R Markdown consultez . +Les données de l'incidence de la varicelle sont disponibles du site Web du [Réseau Sentinelles](http://www.sentiweb.fr/). Nous les récupérons sous forme d'un fichier en format CSV dont chaque ligne correspond à une semaine de la période demandée. Nous téléchargeons toujours le jeu de données complet, qui commence en 1984 et se termine avec une semaine récente. L'URL est: +```{r} +data_url = "http://www.sentiweb.fr/datasets/all/inc-7-PAY.csv" +``` + +Voici l'explication des colonnes donnée sur le [sur le site d'origine](https://ns.sentiweb.fr/incidence/csv-schema-v1.json): + +| Nom de colonne | Libellé de colonne | +|----------------+-----------------------------------------------------------------------------------------------------------------------------------| +| `week` | Semaine calendaire (ISO 8601) | +| `indicator` | Code de l'indicateur de surveillance | +| `inc` | Estimation de l'incidence de consultations en nombre de cas | +| `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) | + +Pour nous protéger contre une éventuelle disparition ou modification du serveur du Réseau Sentinelles, nous faisons une copie locale de ce jeux de données que nous préservons avec notre analyse. Il est inutile et même risquée de télécharger les données à chaque exécution, car dans le cas d'une panne nous pourrions remplacer nos données par un fichier défectueux. Pour cette raison, nous téléchargeons les données seulement si la copie locale n'existe pas. + +```{r} +data_file = "varicelle.csv" + +if (!file.exists(data_file)) { + download.file(data_url, data_file, method="auto") +} +``` + +La première ligne du fichier CSV est un commentaire, que nous ignorons en précisant `skip=1`. +### Lecture +```{r} +data = read.csv(data_file, skip=1) +``` + +Regardons ce que nous avons obtenu: +```{r} +head(data) +tail(data) +``` + +Y a-t-il des points manquants dans nos données ? +```{r} +na_records = apply(data, 1, function (x) any(is.na(x))) +data[na_records,] +``` + +Les deux colonnes qui nous intéressent sont `week` et `inc`. Vérifions leurs classes: +```{r} +class(data$week) +class(data$inc) +``` +Ce sont des entiers, tout va bien ! + + +### Conversion des numéros de semaine + +La gestion des dates est toujours un sujet délicat. Il y a un grand nombre de conventions différentes qu'il ne faut pas confondre. Notre jeux de données utilise un format que peu de logiciels savent traiter: les semaines en format [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601). En `R`, il est géré par la bibliothèque [parsedate](https://cran.r-project.org/package=parsedate): + +```{r} +library(parsedate) +``` + +Pour faciliter le traitement suivant, nous remplaçons ces semaines par les dates qui correspondent aux lundis. Voici une petite fonction qui fait la conversion pour une seule valeur: + +```{r} +convert_week = function(w) { + ws = paste(w) + iso = paste0(substring(ws, 1, 4), "-W", substring(ws, 5, 6)) + as.character(parse_iso_8601(iso)) +} +``` + +Nous appliquons cette fonction à tous les points, créant une nouvelle colonne `date` dans notre jeu de données: +```{r} +data$date = as.Date(convert_week(data$week)) +``` + +Vérifions qu'elle est de classe `Date`: +```{r} +class(data$date) +``` + +Les points sont dans l'ordre chronologique inverse, il est donc utile de les trier dans l'ordre chronologique : +```{r} +data = data[order(data$date),] +``` + +C'est l'occasion pour faire une vérification: nos dates doivent être séparées d'exactement sept jours: +```{r} +all(diff(data$date) == 7) +``` + +### Inspection + +Regardons enfin à quoi ressemblent nos données ! +```{r} +plot(data$date, data$inc, type="l", xlab="Date", ylab="Incidence hebdomadaire") +``` + +Un zoom sur les dernières années montre mieux la localisation des pics en hiver. Le creux des incidences se trouve en été. +```{r} +with(tail(data, 200), plot(date, inc, type="l", xlab="Date", ylab="Incidence hebdomadaire")) +``` -Lorsque vous cliquerez sur le bouton **Knit** ce document sera compilé afin de ré-exécuter le code R et d'inclure les résultats dans un document final. Comme nous vous l'avons montré dans la vidéo, on inclue du code R de la façon suivante: +## L'incidence annuelle -```{r cars} -summary(cars) +### Calcul + +Étant donné que le pic de l'épidémie se situe en hiver, à cheval entre deux années civiles, nous définissons la période de référence entre deux minima de l'incidence, du 1er septembre de l'année $N$ au 1er septembre de l'année $N+1$. Nous mettons l'année $N+1$ comme étiquette sur cette année décalée, car le pic de l'épidémie est toujours au début de l'année $N+1$. Comme l'incidence de syndrome grippal est très faible en été, cette modification ne risque pas de fausser nos conclusions. +L'argument `na.rm=True` dans la sommation précise qu'il faut supprimer les points manquants. Ce choix est raisonnable car il n'y a qu'un seul point manquant, dont l'impact ne peut pas être très fort. + +```{r} +pic_annuel = function(annee) { + debut = paste0(annee-1,"-09-01") + fin = paste0(annee,"-09-01") + semaines = data$date > debut & data$date <= fin + sum(data$inc[semaines], na.rm=TRUE) + } +``` + +Nous devons aussi faire attention aux premières et dernières années de notre jeux de données. Les données commencent en octobre 1984, ce qui ne permet pas de quantifier complètement le pic attribué à 1985. Nous l'enlevons donc de notre analyse. Par contre, pour une exécution en octobre 2018, les données se terminent après le 1er août 2018, ce qui nous permet d'inclure cette année. +```{r} +annees = 1991:2026 +``` + +Nous créons un nouveau jeu de données pour l'incidence annuelle, en applicant la fonction `pic_annuel` à chaque année: +```{r} +inc_annuelle = data.frame(annee = annees, + incidence = sapply(annees, pic_annuel)) +head(inc_annuelle) ``` -Et on peut aussi aisément inclure des figures. Par exemple: +### Inspection -```{r pressure, echo=FALSE} -plot(pressure) +Voici les incidences annuelles en graphique: +```{r} +plot(inc_annuelle, type="p", xlab="Année", ylab="Incidence annuelle") ``` -Vous remarquerez le paramètre `echo = FALSE` 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 utiliser ce paramètre car l'objectif est que vos analyses de données soient parfaitement transparentes pour être reproductibles. -Comme les résultats ne sont pas stockés dans les fichiers Rmd, pour faciliter la relecture de vos analyses par d'autres personnes, vous aurez donc intérêt à générer un HTML ou un PDF et à le commiter. +### Identification des épidémies les plus fortes + +Une liste triée par ordre décroissant d'incidence annuelle permet de plus facilement repérer les valeurs les plus élevées: +```{r} +head(inc_annuelle[order(inc_annuelle$incidence),]) +``` + +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. +```{r} +hist(inc_annuelle$incidence, breaks=10, xlab="Incidence annuelle", ylab="Nb d'observations", main="") +``` + +Calculons les années où l'incidence a été la plus forte et la moins forte : + +```{r} +inc_annuelle[which(inc_annuelle$incidence == max(inc_annuelle$incidence)),] +inc_annuelle[which(inc_annuelle$incidence == min(inc_annuelle$incidence)),] +``` -Maintenant, à vous de jouer! Vous pouvez effacer toutes ces informations et les remplacer par votre document computationnel. diff --git a/module3/exo3/exercice_fr.Rmd b/module3/exo3/exercice_fr.Rmd index 7eece5e296bb586e88166aa8a263ca75b44c2b9e..5643414e48300a52bdbd0dd07948926e8f0940b9 100644 --- a/module3/exo3/exercice_fr.Rmd +++ b/module3/exo3/exercice_fr.Rmd @@ -1,8 +1,11 @@ --- -title: "Votre titre" -author: "Votre nom" -date: "La date du jour" -output: html_document +title: "L'épidémie de choléra à Londres en 1854" +author: "Fanny" +date: "24-08-2026" +output: + pdf_document: default + html_document: + df_print: paged --- @@ -10,24 +13,369 @@ output: html_document knitr::opts_chunk$set(echo = TRUE) ``` -## Quelques explications +# Introduction -Ceci est un document R markdown que vous pouvez aisément exporter au format HTML, PDF, et MS Word. Pour plus de détails sur R Markdown consultez . +## Contexte -Lorsque vous cliquerez sur le bouton **Knit** ce document sera compilé afin de ré-exécuter le code R et d'inclure les résultats dans un document final. Comme nous vous l'avons montré dans la vidéo, on inclue du code R de la façon suivante: +En 1854, le quartier de Soho à Londres a vécu [une des pires épidémies de choléra du Royaume-Uni](https://fr.wikipedia.org/wiki/%C3%89pid%C3%A9mie_de_chol%C3%A9ra_de_Broad_Street), avec 616 morts. Cette épidémie est devenue célèbre à cause de l'analyse détaillée de ses causes réalisée par le médecin [John Snow](https://johnsnowsociety.org/). Ce dernier a notamment montré que le choléra est transmis par l'eau plutôt que par l'air, ce qui était la théorie dominante de l'époque. -```{r cars} -summary(cars) +Un élément clé de cette analyse était une [carte](https://commons.wikimedia.org/wiki/File:Snow-cholera-map-1.jpg) sur laquelle John Snow avait marqué les lieux des décès et les endroits où se trouvaient les pompes à eau publiques. Ces données sont aujourd'hui [disponibles sous forme numérique](http://blog.rtwilson.com/john-snows-cholera-data-in-more-formats). + + + +## Objectifs + + 1. À partir des données numériques, réaliser une carte dans l'esprit de celle de John Snow. Montrer les lieux de décès avec des symboles dont la taille indique le nombre de décès. Indiquer sur la même carte la localisation des pompes en utilisant une autre couleur et/ou un autre symbole. + 2. Par la suite, essayer de trouver d'autres façons pour montrer que la pompe de Broad Street est au centre de l'épidémie, en calculant, par exemple, la densité des décès dans le quartier et l'affichant sur la carte. + + +# Téléchargement des données + +Commençons par récupérer les données relatives à l'épidémie : + +```{r telechargement donnees} +# URL de téléchargement +data_url = "https://rtwilson.com/downloads/SnowGIS_SHP.zip" +data_file = "data_snow" + +# Les données ne sont téléchargées que si elles ne sont pas déjà présentes dans le dossier de travail : +if (!file.exists(data_file)) { + # Téléchargement du dossier zip + download.file(url = data_url, destfile = "data_compressee.zip", mode = "wb") + + # Décompresser le fichier + unzip(zipfile = "data_compressee.zip", exdir = data_file) + + # Supprimer le fichier zip temporaire si besoin + file.remove("data_compressee.zip") +} +``` + +Le ficher $README.txt$ renseigne les informations dont nous avons besoin : + * les fichiers $OSMap$, $OSMap_Greyscale$ et $SnowMap$ sont des fonds de carte ; + * les fichiers $CholeraDeaths$ recensent les morts à un point donné. + * les fichiers $Pumps$ indiquent les coordonnées des pompes. + +Nous utiliserons par la suite les fichiers $.shp$ pour construire nos cartes. Nous allons avoir besoin du package $sf$ : + +```{r sf} +library(sf) +``` + +Chargeons alors les données : + +```{r import donnees} +deaths <- st_read("~/mooc-rr/module3/exo3/data_snow/SnowGIS_SHP/Cholera_Deaths.shp") +pumps <- st_read("~/mooc-rr/module3/exo3/data_snow/SnowGIS_SHP/Pumps.shp") +``` +Et vérifions ce que nous avons obtenu : + +```{r verification donnees} +head(deaths) +tail(deaths) + +head(pumps) +tail(pumps) +``` + +Vérifions qu'il n'y a pas de donnée manquante avant de poursuivre : + +```{r na} +na_records = apply(deaths, 1, function (x) any(is.na(x))) +deaths[na_records,] + +na_records = apply(pumps, 1, function (x) any(is.na(x))) +pumps[na_records,] +``` + +Et vérifions également les classes des données : + +```{r classes} +str(deaths) +str(pumps) +``` + +# Génération de cartes + +## Reproduction de la carte de Snow + +La reproduction de la carte de Snow sera effectuée à l'aides librairies $ggplot2$ et $ggspatial$. Commençons par les charger : + +```{r chargement ggmap} +library(ggplot2) +library(ggspatial) +``` + +Changeons le référentiel pour les coordonnées : + +```{r referentiel} +deaths <- st_transform(deaths, 3857) +pumps <- st_transform(pumps, 3857) +``` + + +Générons à présent la carte. Le fond de carte est importé depuis *OpenStreetMap*. Les décès sont représentés par des points de couleur rouge dont la taille dépend du nombre de morts. Les pompes sont représentées par des carrés bleu. + +```{r premiere carte} +carte_snow <- ggplot() + + # Fond de carte + annotation_map_tile(type = "osm", zoom = 17) + + + # Points correspondant aux décès + geom_sf( + data = deaths, + aes(size = Count), + colour = "red", + fill = "black", + shape = 16, + alpha = 0.8 + ) + + + scale_size_continuous( + name = "Deaths", + range = c(3, 10) + ) + + + # Points correspondant aux pompes + geom_sf( + data = pumps, + # aes(size = Count), + colour = "blue", + fill = "black", + shape = 15, + size = 5, + alpha = 0.8 + ) + + + # Thème + theme_void() + + theme( + legend.position = "right" + ) +``` + +## Ajout de la densité de décès dans le quartier + +Afin de mettre en évidence la place centrale de la pompe de Broad Street dans le foyer épidémique, ajoutons une couche d'information : la densité des décès. + +Commençons par créer un data.frame pour stocker les informations de densité : + +```{r df densite} +death_coords <- st_coordinates(deaths) + +death_df <- data.frame( + x = death_coords[, 1], + y = death_coords[, 2], + Count = deaths$Count +) ``` -Et on peut aussi aisément inclure des figures. Par exemple: +Et générons la carte : + +```{r carte densité} +carte_densite <- ggplot() + + + annotation_map_tile(type = "osm", zoom = 17) + + + # Densité de décès + stat_density_2d( + data = death_df, + aes( + x = x, + y = y, + weight = Count, + fill = after_stat(level), + alpha = after_stat(level) + ), + geom = "polygon", + bins = 10 + ) + + + scale_fill_gradient( + low = "#fee0d2", + high = "#de2d26", + name = "Death density" + ) + + + scale_alpha( + range = c(0.1, 0.3), + guide = "none" + ) + + + # Points correspondant aux décès + geom_sf( + data = deaths, + aes(size = Count), + colour = "black", + fill = "black", + shape = 16, + alpha = 0.8 + ) + + + scale_size_continuous( + name = "Deaths", + range = c(2, 8) + ) + + + # Points correspondant aux pompes + geom_sf( + data = pumps, + # aes(size = Count), + colour = "blue", + fill = "black", + shape = 15, + size = 6, + alpha = 0.8 + ) + + + # Thème + theme_void() + + theme( + legend.position = "right" + ) +``` + +## Position de la pompte de Broad Street + +Faisons ressortir un peu plus la pompe de Broad Street sur la carte. Elle sera un peu plus grosse que les autres et son nom sera écrit sur la carte. + +```{r aes pompe} +# Coordonnées de la pompe de Broad Street +broad_pump <- pumps[1, ] -```{r pressure, echo=FALSE} -plot(pressure) + +carte_densite <- carte_densite + + + # Broad Street pump + geom_sf( + data = broad_pump, + shape = 15, + size = 8, + fill = "blue", + colour = "blue" + ) + + + geom_sf_text( + data = broad_pump, + aes(label = "Broad Street pump"), + nudge_y = -50, + nudge_x = 50, + colour = "blue", + fontface = "bold", + size = 6 + ) + +print(carte_densite) ``` -Vous remarquerez le paramètre `echo = FALSE` 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 utiliser ce paramètre car l'objectif est que vos analyses de données soient parfaitement transparentes pour être reproductibles. +## Quantification du nombre de morts en fonction de la distance à la pompe + +Essayons à présent d'ajouter des cercles concentriques centrés sur la pompe représentant le nombre de morts en fonction de l'éloignement. + +On commence par calculer ces valeurs : + +```{r morts eloignement} +library(dplyr) + +distances <- c(100, 200, 300) + + +# calcul du nombre de morts en fonction de l'éloignement à la pompe +deaths_dist <- deaths |> + mutate( + distance_pump = as.numeric( + st_distance(geometry, broad_pump) + ) + ) + +# et en cumulé +total_deaths <- sum(deaths_dist$Count) -Comme les résultats ne sont pas stockés dans les fichiers Rmd, pour faciliter la relecture de vos analyses par d'autres personnes, vous aurez donc intérêt à générer un HTML ou un PDF et à le commiter. +death_counts <- data.frame( + distance = distances, + deaths = sapply( + distances, + function(d) sum(deaths_dist$Count[deaths_dist$distance_pump <= d]) + ) +) |> + mutate( + percentage = 100 * deaths / total_deaths + ) + +print(death_counts) +``` + +Il faut ensuite créer les cercles : + +```{r cercles} +rings <- do.call( + rbind, + lapply(distances, function(d) { + st_buffer(broad_pump, dist = d) + }) +) +rings$distance <- distances +rings$deaths <- death_counts$deaths +rings$percentage <- death_counts$percentage + +print(rings) +``` + +Et leurs labels : + +```{r labels cercles} +pump_xy <- st_coordinates(broad_pump) + +ring_labels <- data.frame( + x = pump_xy[1, 1] + + distances * cos(35 * pi / 180), + + y = pump_xy[1, 2] + + distances * sin(35 * pi / 180), + + label = paste0( + distances, + " m: ", + death_counts$deaths, + " deaths (", + round(death_counts$percentage), + "%)" + ) +) +``` + + + + +Et on ajoute les cercles à la carte : + +```{r carte cercles} +carte_densite <- carte_densite + + + # Cercles de quantification des décès + geom_sf( + data = rings, + fill = NA, + colour = "black", + linewidth = 0.8, + linetype = "dashed" + ) + + + geom_label( + data = ring_labels, + aes( + x = x, + y = y, + label = label + ), + colour = "black", + fill = "white", + alpha = 0.9, + fontface = "bold", + size = 3.5, + label.size = 0.2 + ) + +print(carte_densite) +``` -Maintenant, à vous de jouer! Vous pouvez effacer toutes ces informations et les remplacer par votre document computationnel.