-
Notifications
You must be signed in to change notification settings - Fork 1
/
code.qmd
569 lines (404 loc) · 25.1 KB
/
code.qmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
---
title: "Géolocalisation de données textuelles"
author: "Pascal Brissette"
format: html
editor: visual
editor_options:
chunk_output_type: console
---
# Introduction
Produire une carte à partir d'un jeu de données trouvé en ligne est désormais une opération assez simple. Quelques lignes de code peuvent suffire, comme le montre l'exemple ci-dessous mettant à profit un jeu de données sur les crimes commis sur le territoire montréalais (l'importation des données peut prendre plusieurs secondes, selon la vitesse de votre connexion internet) :
```{r}
#| echo: true
if(!"geojsonsf" %in% rownames(installed.packages())) {install.packages("geojsonsf")}
if(!"dplyr" %in% rownames(installed.packages())) {install.packages("dplyr")}
if(!"mapview" %in% rownames(installed.packages())) {install.packages("mapview")}
library(geojsonsf)
library(dplyr)
library(mapview)
# Importation d'un fichier comportant les coordonnées géographiques de crimes commis à Montréal
# Élimination à la volée des données non pourvues de coordonnées, puis sélection aléatoire d'un échantillon de 500 observations
geo <- geojson_sf("https://data.montreal.ca/dataset/5829b5b0-ea6f-476f-be94-bc2b8797769a/resource/aacc4576-97b3-4d8d-883d-22bbca41dbe6/download/actes-criminels.geojson") |>
filter(!is.na(LONGITUDE)) |>
slice_sample(n=500)
# Création de la carte avec le jeu de données importé
mapview(geo["CATEGORIE"])
```
On arrive ainsi, avec peu de moyens, à produire grâce à l'extension mapview une carte interactive d'une très grande qualité.
Il faut dire que R possède des extensions de grande qualité développées, soutenues et utilisées par les géographes. Si vous possédez un jeu de données qui comporte les coordonnées géographiques d'objets du monde réel et que ce jeu répond aux standards *Simple Feature Access* (*SF*), le passage vers la représentation cartographique sera pratiquement un jeu d'enfant. Vous trouverez en ligne quantité de cours et d'ateliers qui vous montreront à utiliser les fonctions de l'une ou l'autre des extensions spécialisées.
L'objectif de l'atelier n'est pas d'ajouter à cette documentation abondante. Plutôt, il **vise à faire le pont entre l'analyse des données textuelles et les extensions spécialisées**. Même si l'exercice débouchera, deux fois plutôt qu'une, sur la création de cartes géographiques, on veut prendre le problème en amont de l'exercice cartographique en proposant une chaîne de traitement possible pour passer des données textuelles aux cartes géographiques.
### Objectifs:
- repérer dans des textes des objets du monde réel qui puissent être géolocalisés (sous forme de polygones et sous forme de points), puis extraire les chaînes de caractères représentant ces objets;
- obtenir par croisement de tables et par API (tidygeocoder) les coordonnées géographiques de ces objets;
- projeter les résultats sur des cartes.
Nous allons essayer d'atteindre ces objectifs à travers deux tâches plus précises.
#### Première tâche
La première tâche consistera à extraire de textes de fictions les noms de quartiers de Montréal et à projeter ensuite sur une carte géographique ces mêmes quartiers sous forme de polygones. Une échelle de couleurs sera établie pour traduire la fréquence d'apparition des noms de quartiers dans l'ensemble de la collection de textes.
#### Deuxième tâche
La deuxième tâche consistera à extraire des mêmes textes les mentions des universités montréalaises, à géoréférencer ces universités avec tidygeocoder, puis à projeter sur une carte géographique les points correspondant à ces objets.
## Installation et activation des extensions
Il convient d'abord de préparer l'environnement de travail. La fonction ci-dessous permet d'importer dans l'environnement des extensions si elles ne le sont pas déjà, puis de les activer.
```{r extensions}
#| echo: false
# Création d'une fonction d'installation et d'activation des extensions
inst_ext_fun <- function(extension) {
if(!extension %in% rownames(installed.packages())) {
install.packages(extension, dependencies = TRUE)
}
require(extension, character.only = TRUE)
}
# usage
extensions <-
c(
"ggplot2",
"leaflet",
"leaflet.extras",
"data.table",
"tidygeocoder",
"sf",
"dplyr",
"stringi",
"stringr",
"tmap",
"tmaptools",
"viridis",
"geojsonsf",
"mapview"
)
# Application de la fonction à chaque élément du vecteur `extensions`
sapply(extensions, inst_ext_fun)
```
# Les données textuelles
## Importation et préparation des données
Le jeu de données que nous allons utiliser est celui qui a été exploré dans les précédents ateliers. Il s'agit d'un tableau de données (*data frame*) contenant 563 nouvelles littéraires publiées dans [XYZ: la revue de la nouvelle](https://www.erudit.org/fr/revues/xyz/) entre 2012 et 2022. Les textes ont été moissonnés sur le site [Érudit](https://www.erudit.org/fr/revues/xyz/) par Amélie Ducharme et Yu Chen Shi, sous la supervision de Julien Vallières-Gingras.
```{r}
# Lecture du jeu de données
xyz <-
data.table::fread("donnees/donnees_importees/xyz.csv")
# Observer la structure
str(xyz)
# Il n'y a pas d'identifiant unique. On peut en composer en utilisant, dans les URL moissonnés, les séquences numériques uniques.
xyz$doc_id <-
as.integer(
str_sub(
xyz$URI, start = -7L, end = -3L
)
)
# Vérifier que les doc_id sont uniques
table(!duplicated(xyz$doc_id))
# Observer à nouveau la structure
str(xyz)
# La variable "Date" contient l'année. On peut extraire cette information et l'emmagasiner dans une nouvelle colonne
xyz$annee <- as.integer(str_extract(string = xyz$Date, pattern = "[0-9]+"))
## Exercice: créez une table montrant la distribution des numéros par année
# table()
# Faire le même exercice avec la variable `numéro`. Que remarquez-vous?
table(xyz$Numéro)
# Il faut d'abord extraire les nombres (irrégularité dans l'entrée de données)
# L'argument `pattern` est une expression régulière. Pourriez-vous l'expliquer?
xyz$Numéro <- as.integer(str_extract(xyz$Numéro, pattern = "[0-9]{1,3}"))
# Essayer à nouveau
table(xyz$Numéro)
# Hourra!
# Donner des noms adéquats aux colonnes
colnames(xyz) <-
c("titre",
"auteur",
"numero",
"Date",
"theme",
"url",
"texte",
"doc_id",
"annee")
# Allègement de la structure de données
xyz <- xyz[, c("doc_id", "titre", "auteur", "numero", "annee", "theme", "texte")]
# str(xyz)
# Exporter cette table
# fwrite(xyz, "donnees/donnees_produites/csv/combined_table_net_xyz.csv")
```
## Première tâche
### Les quartiers montréalais comme objets géographiques
#### Les données géographiques
Pour que des lieux physiques puissent être transposés sur une carte géographique, il faut en proposer une représentation qui respecte un ensemble de normes. La norme *Simple Feature Access* est celle que les spécialistes suivent dans la construction, le stockage et le traitement des objets pourvus d'attributs géographiques.
Dans R, l'extension `sf` implémente cette norme *Simple Feature Access* (ou simplement *SF*). Ce qu'on appelle *feature* peut être conçu comme un objet du monde réel: un immeuble, une place publique, une ville, un cours d'eau, une forêt, une chaîne de montagnes. Une ville par exemple, selon la perspective (le point dans l'espace depuis lequel on la considère), sera représentée par un point, un polygone ou un ensemble de polygones (si elle est traversée par des cours d'eau). Une rivière prendra généralement la forme d'une série de points formant une ligne brisée, et ainsi de suite. Les points, les polygones, les multipolygones et les lignes sont les principales formes avec lesquels on représente les objets sur une carte. Un objet géoréférencé aura d'autres attributs (exemple: population, température moyenne, altitude, etc.). Toutes ces données, géographiques et autres, seront emmagasinées selon la norme SF dans un tableau de données, une structure comportant deux dimensions (avec lignes et colonnes).
Dans le bloc suivant, nous allons importer un fichier avec une extension .shp (*shapefile*). Il a été récupéré sur le site de [Données Québec](https://www.donneesquebec.ca/recherche/dataset/vmtl-quartiers-sociologiques) et contient les données géographiques des quartiers sociologiques de Montréal. Nous allons supprimer certaines colonnes sans intérêt immédiat, puis y ajouter une nouvelle colonne appelée `regex` (pour "expression régulière"). Ces expressions régulières permettront ensuite d'associer les noms de quartiers trouvés dans les textes du corpus à des noms de quartier standardisés.
```{r}
# Importation d'une table comprenant les noms de quartiers et les coordonnées correspondant à leurs délimitations
quartiersGeoMtl <-
sf::read_sf(
"donnees/donnees_importees/quartiers_sociologiques_2014/quartiers_sociologiques_2014.shp"
)
# print(quartiersGeoMtl)
# str(quartiersGeoMtl)
# Sélection des colonnes d'intérêt
quartiersGeoMtl <- quartiersGeoMtl[, c("Q_socio", "Abrev", "geometry")]
# Observation de cette structure de données
str(quartiersGeoMtl)
# Ajout d'une colonne avec 32 expressions régulières, une pour chaque nom de quartier.
quartiersGeoMtl$regex <- c(
"[Aa]huntsic",
"[Bb]ordeaux.[Cc]artierville",
"[Aa]njou",
"([Cc][ôo]te.des.[Nn]eiges)|(cdn|CDN)",
"([Nn]otre.[Dd]ame.de[Gg]r[aâ]ce)|(NDG|ndg\b)",
"[Nn]ord.[Oo]uest.{1,14}[Mm]ontréal",
"[Ll]achine",
"[Ll]a[Ss]alle",
"[Hh]ochelag",
"[Mm]ercier.[Oo]uest",
"[Mm]ercier.[Ee]st",
"[Mm]ontréal.[Nn]ord",
"[Oo]utremont",
"([Pp]lateau.[Mm]ont.[Rr]oyal)|le Plateau",
"[Pp]ointe.aux.[Tt]rembles",
"[Rr]ivière.des.[Pp]rairies",
"[Pp]etite.[Pp]atrie",
"[Rr]osemont",
"[Vv]ille.[Ss]aint.[Ll]aurent",
"[Ss]aint.[Ll]éonard",
"[Pp]etite.[Bb]ourgogne",
"([Pp]ointe.[Ss]aint.[Cc]arles)|(\bpsc\b|PSC)",
"[Ss]aint.[Hh]enri",
"([Vv]ille.[EÉée]mard|[Cc][ôo]te.[Ss]aint.[Pp]aul)",
"[Vv]erdun",
"[Cc]entre.[Ss]ud",
"[Ff]aubourg.[Ss]aint.[Ll]aurent",
"([Pp]eter|[Qq]artier).[Mm]c.?[Gg]ill",
"[Vv]ieux.[Mm]ontréal",
"[Pp]arc.[Ee]xtension",
"[Ss]aint.[Mm]ichel",
"[Vv]illeray"
)
# On peut faire un test d'indexation avec avec Côte-des-Neiges (4e expression régulière)
# xyz[texte %like% quartiersGeoMtl$regex[4]]
```
### Extraction des noms de quartiers dans les textes
Les expressions régulières permettront de repérer sinon la totalité, du moins le plus grand nombre de mention des noms de quartiers dans les textes du corpus. Ces expressions seront d'abord transformées en un seul long vecteur, chaque expression étant séparée des autres par l'opérateur `|` (équivalent de "ou"). Le vecteur sera ensuite projeté dans les textes du corpus et attrapera, pour ainsi dire, les noms de quartiers. Chaque fois qu'un texte comprendra une chaîne de caractères répondant aux critères de l'expression, cette chaine sera extraite du texte et placée dans une nouvelle colonne appelée `quartiers_nommes`.
```{r}
# Première étape: créer une seule et longue regex avec celles de la colonne du même nom
regex_tous_quartiers <- paste(quartiersGeoMtl$regex, sep = "", collapse = "|")
# Extraction des noms avec cette expression régulière. Les chaînes ainsi extraites seront placées dans une nouvelle colonne appelée "quartiers_nommes".
xyz$quartiers_nommes <- sapply(xyz$texte, str_extract_all, pattern = regex_tous_quartiers)
# str(xyz)
# Élimination des doublons
xyz$quartiers_nommes <- sapply(xyz$quartiers_nommes, unique)
# L'opération d'extraction a généré des listes.
# On peut assembler les éléments de ces listes avec `paste()`
xyz$quartiers_nommes <- sapply(xyz$quartiers_nommes, paste, collapse = "; ")
# Vérification du succès de l'opération
xyz[quartiers_nommes != "", .(quartiers_nommes)]
# Conversion des chaines extraites des textes en noms officiels
xyz$quartiers_nommes <- stri_replace_all_regex(
xyz$quartiers_nommes,
pattern = quartiersGeoMtl$regex,
replacement = quartiersGeoMtl$Q_socio,
vectorize = FALSE
)
```
### Constitution d'une table pour visualisation
Nous avons maintenant deux tables à notre disposition. La première contient les textes et les métadonnées, ainsi qu'une colonne où sont indiqués les quartiers nommés dans les textes. La deuxième est un un objet de type SF et contient ces mêmes noms de quartiers associés à des coordonnées géographiques. Pour passer à la prochaine étape, soit la projection de la fréquence des mentions de quartiers dans une carte géographique, nous devons créer une troisième table qui contiendra trois informations: le **nom du quartier**, le **nombre de fois que ce quartier est mentionné dans l'ensemble du corpus**, et les **données géographiques** de ces quartiers.
```{r}
# Création d'une liste comprenant tous les noms de quartiers
quartiers_nommes_sep_l <- strsplit(xyz$quartiers_nommes, "; ")
# Élimination des éléments sans contenu
valeurs_non_nulles <- which(quartiers_nommes_sep_l != "character(0)")
quartiers_nommes_sep_l <- quartiers_nommes_sep_l[valeurs_non_nulles]
# Extraction des noms emmagasinés dans la liste et transfert de ces noms dans un tableau de données
quartiers_empiles <- data.table(
Q_socio = c(
sapply(quartiers_nommes_sep_l, "[", 1),
sapply(quartiers_nommes_sep_l, "[", 2),
sapply(quartiers_nommes_sep_l, "[", 3),
sapply(quartiers_nommes_sep_l, "[", 4)
)
)
# Calcul de la fréquence des noms de quartiers
freq_quartiers <- quartiers_empiles[!is.na(Q_socio) , .N, "Q_socio"]
# En base R, la même opération serait faite comme suit:
# quartiers_empiles_sansNA <- quartiers_empiles[!is.na(quartiers_empiles$Q_socio),]
# freq_quartiers_df <- data.frame(Q_socio = names(table(quartiers_empiles_sansNA)),
# N = unname(as.integer(table(quartiers_empiles_sansNA))))
# On joint maintenant la table de fréquence et celle contenant les coordonnées géographiques
freq_quartiers_geo <- left_join(
quartiersGeoMtl[, c("Q_socio", "Abrev", "geometry")],
freq_quartiers, by ="Q_socio"
)
# Cette opération a introduit dans la table de fréquence des noms de quartiers qui n'y étaient pas et dont la fréquence est NA. Nous allons transformer ces NA en 0.
freq_quartiers_geo$N <- ifelse(
is.na(freq_quartiers_geo$N),
0,
freq_quartiers_geo$N
)
```
### Les graphiques
Comme n'importe quel jeu de données, celui que nous avons créé peut être observé sous la forme d'un diagramme de dispersion ou à points.
```{r}
ggplot(freq_quartiers_geo, aes(x=reorder(Q_socio, N), y=N, colour = N, size = N))+
geom_jitter(stat = "identity")+
coord_flip()+
theme_classic()
```
Un tel diagramme ne tire cependant pas parti des données géographiques du tableau. L'extension ggplot2 qu'on vient d'utiliser pour créer le diagramme de dispersion permet d'ajouter une couche graphique. La fonction prend en entrée l'objet `sf` et repère automatiquement la colonne `geo` contenant les coordonnées de polygones.
```{r}
ggplot()+
geom_sf(data=freq_quartiers_geo, aes(fill=-N))
```
Dans la suite de l'atelier, on utilisera plutôt des extensions spécialisées.
### Projection des dimensions dans l'espace géographique
Plusieurs extensions permettent d'utiliser les données géographiques pour produire des cartes statiques et interactives. Leaflet et tmap sont parmi les plus utilisées. D'autres, comme mapview, s'appuient sur leaflet et simplifient le processus. Vous trouverez en ligne une documentation abondante et plusieurs exemples avec divers jeux de données
### L'extension tmap
L'extension tmap fonctionne sur le principe de la grammaire des graphiques dont il a été question dans le précédent atelier sur ggplot2. On fournit à la fonction d'entrée `tm_shape()` un jeu de données et on ajoute ensuite des couches pour ajuster les formes et autres éléments tels les titres, symboles, légendes, etc.
```{r}
tmap_mode("plot")
# Fonction de base, à laquelle on ajoute les polygones
tm_shape(freq_quartiers_geo) + tm_fill(col = "N", palette = "viridis") +
tm_layout(legend.height = 0.5)
# Avec des tranches
tm_shape(freq_quartiers_geo) + tm_polygons(col = "N", breaks = c(0,3,5), palette = "viridis") +
tm_layout(legend.height = 0.5)
# Avec algorithme (jenks = identification des groupes similaires)
tm_shape(freq_quartiers_geo) + tm_polygons(col = "N", style = "jenks", palette = "viridis") +
tm_layout(legend.height = 0.5)
# Avec une seule couleur par catégorie
tm_shape(freq_quartiers_geo) + tm_polygons(col = "N", style = "cat", palette = "viridis") +
tm_layout(legend.height = 0.5)
# Ajout de composantes graphiques (boussole, titres, etc.)
freq_shape <- tm_shape(freq_quartiers_geo) + tm_polygons(col = "N", style = "cat", palette = "viridis") +
tm_layout(legend.height = 0.5)
# Ajout d'une boussole
freq_shape + tm_compass(type = "8star", position = c("left", "top"))
# Ajout d'un titre
freq_shape + tm_layout(title = "Quartiers montréalais dans les nouvelles\nde la revue XYZ")
# Taille des éléments
freq_shape + tm_layout(title = "Quartiers montréalais dans les nouvelles\nde la revue XYZ", title.size = 0.8)
# Couleur de l'arrière-plan
freq_shape + tm_layout(title = "Quartiers montréalais dans les nouvelles\nde la revue XYZ", title.size = 0.8, bg.color = "grey85")
# Élimination du cadre
freq_shape + tm_layout(title = "Quartiers montréalais dans les nouvelles\nde la revue XYZ", title.size = 0.8, frame = FALSE)
# Ajout d'un titre et des crédits, puis déplacement de la légende
freq_shape + tm_layout(title = "Quartiers montréalais dans les nouvelles\nde la revue XYZ", scale = 0.7, frame = FALSE) +
tm_credits("Source des données: XYZ", position = c("right", "BOTTOM"))
# Utilisation d'une feuille de styles
tm_shape(freq_quartiers_geo) + tm_polygons(col = "N") + tm_style("bw")
tm_shape(freq_quartiers_geo) + tm_polygons(col = "N") + tm_style("classic")
tm_shape(freq_quartiers_geo) + tm_polygons(col = "N") + tm_style("cobalt")
tm_shape(freq_quartiers_geo) + tm_polygons(col = "N") + tm_style("col_blind")
# Ajout des abréviations de quartiers (ici, on aurait pu conserver et utiliser les codes de quartiers pour éviter les superpositions)
tm_shape(freq_quartiers_geo) + tm_polygons(col = "N") +
tm_style("col_blind") +
tm_text("Abrev", size = 0.4)
```
## Deuxième tâche
Nous allons maintenant composer un vecteur comprenant quatre expressions régulières. Elles seront utilisées pour extraire des textes les noms des universités montréalaises.
```{r}
# Expressions régulières unies en une seule chaîne de caractères
regex_univ <- c("université.de.montréal|\\bu\\.?de?\\.?m\\.?\\b|université.du.québec.à.montréal|\\buq[aà]m\\b|concordia|mcgill")
# Extraction des noms
xyz[, univ_nommees:=str_extract_all(tolower(texte), regex_univ)]
# Remplacement des character(0) par NA dans la nouvelle colonne du tableau
xyz$univ_nommees <- lapply(xyz$univ_nommees, function(x) if(identical(x, character(0))) "" else x)
# Élimination des doublons
xyz[, univ_nommees:=lapply(univ_nommees, unique)]
# L'opération d'extraction a généré des listes.
# On peut assembler les éléments de ces listes avec `paste()`
xyz$univ_nommees <- sapply(xyz$univ_nommees, function(x) paste(x, collapse = "; "))
# Vérification de l'opération
xyz[univ_nommees != "", .(univ_nommees)]
# Les noms étant uniformes et "propres", nous n'aurons pas besoin de les normaliser comme on l'a fait pour les noms de quartiers.
```
## Création d'une table de fréquence avec les entités géographiques
```{r}
# Création d'une liste comprenant tous les noms de quartiers
univ_nommees_sep_l <- strsplit(xyz$univ_nommees, "; ")
# Élimination des éléments sans contenu
valeurs_non_nulles <- which(univ_nommees_sep_l != "character(0)")
univ_nommees_sep_l <- univ_nommees_sep_l[valeurs_non_nulles]
# On vérifie le nombre maximal de valeurs uniques dans chaque texte
max(sapply(univ_nommees_sep_l, length))
# Transposition des données dans un tableau
univ_empilees <- data.table(
nom_univ = c(
sapply(univ_nommees_sep_l, "[", 1),
sapply(univ_nommees_sep_l, "[", 2)
)
)
# Table de fréquences
freq_univ <- univ_empilees[
!is.na(nom_univ) , .N, "nom_univ"][
order(N, decreasing = TRUE)
]
# Pour faciliter le géoréférencement, nous allons ajouter une colonne avec l'adresse de chaque institution
freq_univ$adresse <- c("3150, rue Jean-Brillant, Montreal, Quebec, Canada",
"1430, rue Saint-Denis, Montreal, Quebec, Canada",
"845, rue Sherbrooke Ouest, Montreal, Quebec, Canada",
"1455, boulevard de Maisonneuve Ouest, Montreal, Quebec, Canada")
```
## Travailler avec Tidygeocoder
Nous sommes maintenant prêts à géoréférencer nos données. Les adresses seront passées à la fonction `geocode()` de l'extension tidygeocoder. Celle-ci traduit nos requêtes, écrites en langage R, dans un format que l'API puisse interpréter (normalement json). La réponse de l'API, une fois reçue par tidygeocoder, est transformée en un tableau de données de type `tibble`. Si vos adresses ne sont pas déjà intégrées à un tableau de données, vous pouvez les passer sous la forme d'un vecteur à la fonction `tidygeocoder::geo()`. Essayez par exemple avec une adresse que vous connaissez bien.
```{r}
# Exercice: remplacer l'adresse dans l'instruction ci-dessous par une adresse de votre choix, puis observez le résultat.
mon_adresse <- geo(address = "1000, rue de la Gauchetière, Montréal, Québec, Canada")
```
Comme nos adresses sont dans un tableau de données, nous allons utiliser la fonction `geocode()`. Nous allons ensuite transformer le tableau de données en un objet de type *Simple Feature*.
```{r}
# Géoréférencement des universités montréalaises
freq_univ_geo <- freq_univ |> tidygeocoder::geocode(address = adresse, method = "osm")
# Transformation du tableau de données en objet Simple Feature
freq_univ_geo_sf <- st_as_sf(freq_univ_geo, coords = c("long", "lat"), crs = st_crs(4326))
# Création d'une colonne avec des abréviations
freq_univ_geo_sf$Abrev <- c("UdeM", "UQAM", "McGill", "Concordia")
# Si le géoréférencement échoue, vous pouvez exécuter l'instruction ci-dessous
# freq_univ_geo_sf <- readRDS("donnees/donnees_produites/rds/freq_univ_geo_sf.RDS")
```
Les coordonnées du polygone de l'île de Montréal pourront nous être utilisées pour créer une couche sur laquelle les points seront déposés.
```{r}
# Importation des coordonnées à partir du site de la Ville de Montréal
mtl_poly <- geojson_sf("https://data.montreal.ca/dataset/b628f1da-9dc3-4bb1-9875-1470f891afb1/resource/92cb062a-11be-4222-9ea5-867e7e64c5ff/download/limites-terrestres.geojson")
# Observation rapide de la forme
mtl_poly |> mapview()
```
Nous sommes maintenant prêts à projeter les points sur un plan géographique. Nous utiliserons la fonction `tm_bubbles()`, qui permet d'adapter le volume des points à une variable numérique (notre variable `N`):
```{r}
tmap_mode("plot")
tm_shape(mtl_poly) + tm_polygons() +
tm_shape(freq_univ_geo_sf) + tm_bubbles(size = "N", col = "red")
tmap_mode("view")
tm_shape(mtl_poly) + tm_polygons() +
tm_shape(freq_univ_geo_sf) + tm_bubbles(size = "N", col = "red")
# Le mode "view" permet d'utiliser des couches de base variées:
tmap_mode("view")
# Modification de paramètres
tm_basemap(server = "Stamen.Toner") +
tm_shape(mtl_poly) + tm_polygons(col="white", border.col = "blue") +
tm_shape(freq_univ_geo_sf) + tm_bubbles(size = "N", col = "red", scale = 3)
# Le mode "plot" permet de d'ajouter d'autres éléments visuels
tmap_mode("plot")
tm_shape(mtl_poly) + tm_polygons(col="white", border.col = "blue") +
tm_shape(freq_univ_geo_sf) + tm_bubbles(size = "N", col = "red", scale = 3)+
tm_text(text = "Abrev", size = 0.5)+
tm_credits("Source des données: Revue XYZ") +
tm_layout(main.title = "Universités montréalaises dans\nles nouvelles de la revue XYZ",
fontface = "bold",
title.size = 0.5)
# Fonction de sauvegarde
mtl_univ_plot <- tm_shape(mtl_poly) + tm_polygons(col="white", border.col = "blue") +
tm_shape(freq_univ_geo_sf) + tm_bubbles(size = "N", col = "red", scale = 3)+
tm_text(text = "nom_univ", size = 0.5)+
tm_credits("Source des données: Revue XYZ") +
tm_layout(main.title = "Universités montréalaises dans\nles nouvelles de la revue XYZ",
fontface = "bold",
title.size = 0.5)
tmap_save(
tm = mtl_univ_plot,
filename = "donnees/donnees_produites/graphiques/mtl_univ_plot.png"
)
# Exercice:
# Modifiez l'échelle et la couleur des bulles
# Modifiez les modes de visualisation ("plot", "view")
# La fonction `tm_basemap()` permet d'importer des toiles de fond variées. Remplacez "Stamen.Toner" par "Stamen.Watercolor" ou "Esri.WorldImagery". D'autres options sont proposées https://leaflet-extras.github.io/leaflet-providers/preview/
```
# Pour aller plus loin
Jesse Cambon, Diego Hernangomez, Christopher Belanger, Daniel Possenriede, "Tidygeocoder: An R package for geocoding", 2021. DOI: <https://doi.org/10.21105/joss.03544>
Lovelace, Robin, Jakub Nowosad et Jannes Muenchow, *Geocomputation With R*, 2020. URL: [https://r.geocompx.org/index.html](https://r.geocompx.org/index.htmlhttps://r.geocompx.org/index.html)
Martijn Tennekes et Jakub Nowosad, *Elegant and Informative Maps With Tmap*, 2021. URL: <https://r-tmap.github.io/tmap-book/>