L’objectif est de mettre en pratique les techniques présentées dans le tutoriel, à partir de nouveaux jeux de données.
Les objectifs et les données utilisées
Pour cela, on utilise un jeu de données en open-data : les parkings publics géolocalisés situés dans l’agglomération bordelaise. Les données ont été téléchargées sur le site de l’open-data de Bordeaux Métropole et ont été retravaillées pour les besoins de l’exercice (script ici pour plus de détails).
Par ailleurs, notre objectif sera d’étudier la situation du centre-ville de Bordeaux en termes de présence de places de stationnement, de proportion de places adaptées aux personnes à mobilité réduite et au prix de ces places. Le contour géographique du centre-ville de Bordeaux est fourni. À noter qu’il a été créé “à la main” par les auteurs de ce TP, et qu’il ne répond à aucune définition officielle ou urbanistique précise.
Par ailleurs, à la fin de ce TP, une dernière partie consistera à approximer le nombre d’habitants vivant dans le centre-ville de Bordeaux d’après les données Filosofi carroyées.
Installation de la session et importation des données
Installation des packages
Avant de débuter les exercices, on installe tous les packages nécessaires :
## Liste des librairies utiliséespackages <-c("dplyr", "sf", "mapsf", "mapview", "btb")## Vérifier si la librairie est installée, si non l'installer, puis la chargerpackage.check <-lapply( packages,FUN =function(x) {if (!require(x, character.only =TRUE)) {install.packages(x, dependencies =TRUE)library(x, character.only =TRUE) } })
# pour paramétrer mapviewmapviewOptions(leafletWidth ="100%")# Options globales pour les cartes avec mapview mapviewOptions(basemaps =c("OpenStreetMap", "Esri.WorldImagery"))
Chargement des données
Le code ci-dessous permet d’importer les données utilisées dans ce tutoriel. Elles sont stockées sous Minio, dans le “bucket public” : s3/projet-formation/r-lissage-spatial/.
Quelques informations concernant ces jeux de données :
parking.RDS : table de données géolocalisées concernant les parkings publics dans l’agglomération bordelaise. Attention : on parle de parking publics et non de places de stationnements ! Pour chaque parking public, voici les variables renseignées :
ident : identifiant du parking public
exploit : exploitant
np_global : nombre total de places de stationnement
np_pmr : nombre de places de stationnement pour les personnes à mobilité réduite
th_heur : prix horaire
x : longitude
y : latitude
epsg : code EPSG (projection géographique)
bordeaux_centre.gpkg : découpage à façon du centre-ville de Bordeaux2.
Pour visualiser les résultats de vos lissages, on crée une fonction generCarte de cartographie s’appuyant sur le package mapsf. On pourra réutiliser cette fonction par la suite, et limiter ainsi le nombre de lignes à recopier dans le code à chaque exercice.
Pour importer cette fonction dans votre environnement global, copier-coller et executer le code ci-dessous.
generCarte <-function(sfCar, nomvar, nbreaks =5, zone, titre ="titre"){#'@param sfCar : Table de carreaux#'@param nomvar : Nom de la variable à cartographier#'@param nbreaks : Nombre de classes à représenter sur la carte (avec méthode des quantiles)#'@param zone : Polygone de la zone d'intérêt (ex : centre de Bordeaux)#'@param titre : Titre de la carte (chaîne de caracères)#'@returns : carte produite avec le package mapsfmf_map(x = sfCar, type ="choro",var = nomvar,breaks ="quantile",nbreaks = nbreaks,lwd =0.2,leg_pos ="topright")mf_map(x = zone, lwd =4,col =NA, add =TRUE)mf_layout(title = titre, credits ="Insee-DSAU, Bordeaux Métropole, IGN, mapsf")}
Phase 1 : Appropriation des données
NoteExercice 1
Répondre aux questions suivantes :
Combien de parkings publics sont répertoriés dans la base parkings ?
Vérifier qu’il n’y a pas de données manquantes dans les variables de positions géographiques.
Regarder la distribution des variables (avec la fonction summary)
# 87 parkings dans la base# Absence de valeurs manquantes dans les xy ? => Vraisum(is.na(parkings$x))
[1] 0
sum(is.na(parkings$y))
[1] 0
# Distribution des variablesparkings %>%summary()
ident exploit np_global np_pmr
Length :87 Length :87 Min. : 46.0 Min. : 0.00
N.unique :87 N.unique : 9 1st Qu.: 162.0 1st Qu.: 4.00
N.blank : 0 N.blank : 0 Median : 341.0 Median : 7.00
Min.nchar: 7 Min.nchar: 6 Mean : 473.9 Mean : 9.08
Max.nchar: 8 Max.nchar:19 3rd Qu.: 528.5 3rd Qu.:10.50
Max. :3427.0 Max. :57.00
th_heur x y epsg
Min. : 0.000 Min. :407551 Min. :6414710 Length :87
1st Qu.: 2.400 1st Qu.:415311 1st Qu.:6420763 N.unique : 1
Median : 3.100 Median :417608 Median :6421969 N.blank : 0
Mean : 3.296 Mean :416684 Mean :6422432 Min.nchar: 4
3rd Qu.: 4.050 3rd Qu.:418911 3rd Qu.:6424019 Max.nchar: 4
Max. :14.500 Max. :422710 Max. :6433813
NoteExercice 2
Observer l’emprise du contour du centre-ville de Bordeaux en utilisant la fonction mapview.
SolutionSolution 2
mapview(centreBdx)
NoteExercice 3
Transformer la base des parkings en format vectoriel (en gardant les colonnes x et y, nécessaires pour la suite) et enregistrer la résultat dans la nouvelle variable sfParkings.
Cartographier conjointement le contour de Bordeaux-centre et les parkings en utilisant mapview.
Tip
Pour transformer la base des parkings en format vectoriel, utiliser la fonction st_as_sf. Attention à bien renseigner le système de projection des coordonnées x, y dans le paramètre crs.
Tip
Pour cartographier avec mapview, on additionne les couches vectorielles avec un + : mapview(polygone) + mapview(points).
SolutionSolution 3
# 1. Transformation en objet vectoriel (géographique)sfParkings <- parkings %>%mutate(lon = x, lat = y) %>%st_as_sf(coords =c("lon", "lat"), crs =2154)# 2. Cartographie avec mapviewmapview(centreBdx) +mapview(sfParkings, col.region ="black")
Phase 2 : Le lissage spatial
Partie 2.1 : Carroyer les données avant de lisser
Dans le cas présent, le petit nombre de parkings ne rend pas indispensable cette phase de carroyage. Elle permet néanmoins de s’approprier un peu plus la structure spatiale des données avec le lissage.
NoteExercice 4
Créer une constante iCellSize <- 1000 correspondant à la taille des carreaux souhaitée
Créer la table centroides contenant les centroïdes x_centro et y_centro des carreaux de 1000m à partir de la table parkings.
Comptabiliser le nombre de parkings contenus dans chaque carreau et créer une nouvelle variable nbParkings.
Tip
Utiliser la fonction btb_add_centroids
Pour information, les variables x_centro et y_centro correspondent respectivement aux variables x et y auxquelles :
On retire le reste de leurs divisions euclidiennes modulo 1000 pour déterminer le point en bas à gauche du carreau de 1km.
Puis on ajoute 1000/2 pour tomber sur le centre du carreau
Tip
En groupant la base de parkings sur le couple de centroïdes, on aboutit à la base souhaitée.
SolutionSolution 4
# 1. Taille des carreauxiCellSize =1000# 2. Centroïdescentroides <-btb_add_centroids(pts = parkings, iCellSize = iCellSize)# 3. Compter le nombre de parkings par carreaucentroides <- centroides %>%group_by(x_centro, y_centro) |>count(name ="nbParkings")head(centroides)
Transformer centroides en grille de carreaux et stocker le résultat dans la variable sfCarreaux.
Restreindre cette base aux seuls carreaux intersectant le centre de Bordeaux.
Cartographie les carreaux et le contour du centre de Bordeaux avec generCarte.
Tip
La fonction btb_ptsToGrid permet de créer la grille de carreaux.
Tip
Utiliser la fonction st_join par exemple pour réaliser l’intersection.
Tip
Utiliser la fonction generCarte
SolutionSolution 5
# 1. Générer la grillesfCarreaux <-btb_ptsToGrid(pts = centroides, sEPSG ="2154",iCellSize = iCellSize)# 2. Restriction du champ : on ne retient que les carreaux intersectant Bordeaux-centresfCarreaux <- sfCarreaux %>%st_join(centreBdx, left = F)# 3. CartographiegenerCarte(sfCar = sfCarreaux, nomvar ="nbParkings", nbreaks =3,zone = centreBdx, titre ="Nombre de parkings sur Bordeaux")
Partie 2.2 : Lissage de la densité des parkings
NoteExercice 6
Créer un “buffer” du centre-ville de Bordeaux (avec une marge de 3 000 mètres autour) et enregistrer le résultat dans centreBdxBuffer.
Représenter le centre de Bordeaux et son buffer avec la librairie mapview
Sélectionner les parkings positionnés dans cette zone tampon et enregistrer la nouvelle table parkingsBuff.
Attention : cette nouvelle table doit garder des colonnes x et y en vue du carroyage.
Tip
Utiliser la fonction st_buffer
Tip
Utiliser la fonction st_join
SolutionSolution 6
# 1. Création d'un buffer autour du territoiremarge <-3000centreBdxBuffer <-st_buffer(centreBdx, dist = marge)# 2. Cartographie avec mapviewmapview(centreBdxBuffer, col.region="gray") +mapview(centreBdx)# 3. Réduire la base aux seules observations dans le territoireparkingsBuff <-st_join(sfParkings, centreBdxBuffer, left = F)parkingsBuff
NoteExercice 7
Créer une variable nbObsLisse = 1L dans parkingsBuff. Que représente-t-elle ?
Lisser le nombre de parkings dans le buffer du centre-ville de Bordeaux :
Avec un rayon de lissage de 1 700 mètres
En générant une grille carroyée de 50 mètres de côté
Restreindre les carreaux de 50 mètres obtenus aux seuls carreaux intersectant le centre-ville et enregistrer le résultat dans sfCarLisse
Cartographier le résultat obtenu avec la fonction generCarte.
[BONUS] Proposer une transformation permettant d’obtenir une densité au km².
Tip
Utiliser bien sûr la fonction btb_smooth !
SolutionSolution 7
# 1. Nouvelle variable nbObsLisseparkingsBuff$nbObsLisse <-1L#### C'est une variable de "comptage des observations".# 2. Lissagerayon <-1700# Rayon de lissagetcar <-50# Taille des carreaux de la grillesfCarLisse <-btb_smooth(pts = parkingsBuff[, c("nbObsLisse", "x", "y")], sEPSG ="2154",iCellSize = tcar, iBandwidth = rayon)# 3. Filtrage : ne garder que les carreaux intersectant le centre de BordeauxsfCarLisse <- sfCarLisse %>%st_join(centreBdx, left = F)# 4. Carte lissée avec mapsfgenerCarte(sfCar = sfCarLisse, nomvar ="nbObsLisse", nbreaks =5, zone = centreBdx,titre =paste0("Lissage de la densité de parkings avec un rayon de ", rayon, " m"))
#5. densité au km2sfCarLisse$nbObsLisse_km2 <- sfCarLisse$nbObsLisse * ((1000/ tcar) ^2)generCarte(sfCar = sfCarLisse, nomvar ="nbObsLisse_km2", nbreaks =5, zone = centreBdx,titre =paste0("Lissage de la densité (km2) de parkings avec un rayon de ", rayon, " m"))
NoteExercice 8
Refaire le lissage avec un rayon de 600 mètres, puis avec un rayon de 3000 mètres. Essayer de créer une fonction générale pour automatiser vos traitements.
SolutionSolution 8
lissage_maison <-function(rayon){ sfCarLisse <-btb_smooth(pts = parkingsBuff[, c("nbObsLisse", "x", "y")], sEPSG ="2154",iCellSize = tcar, iBandwidth = rayon) sfCarLisse <- sfCarLisse %>%st_join(centreBdx, left = F) %>%mutate(nbObsLisse = nbObsLisse * (1000/ tcar) ^2)generCarte(sfCar = sfCarLisse, nomvar ="nbObsLisse", nbreaks =5, zone = centreBdx,titre =paste0("Lissage de la densité de parkings avec un rayon de ", rayon, " m"))}# cartographies :lissage_maison(600)
lissage_maison(3000)
Partie 2.3 : Lissage du nombre de places de parkings
NoteExercice 9
Lisser le nombre de places de stationnement (variable np_global), et non plus le nombre de parkings.
Remarque : Pour la suite, toujours prendre un rayon de lissage de 1 700 mètres sauf mention contraire.
SolutionSolution 9
rayon <-1700sfCarLisse <-btb_smooth(pts = parkingsBuff[,c("np_global", "x", "y")], sEPSG ="2154",iCellSize = tcar, iBandwidth = rayon)# Filtrage des carreaux lissés dans Bordeaux centresfCarLisse <- sfCarLisse %>%st_join(centreBdx, left = F) %>%mutate(np_global = np_global * (1000/ tcar) ^2)# Carte lisséegenerCarte(sfCar = sfCarLisse, nomvar ="np_global", nbreaks =5, zone = centreBdx,titre ="Lissage des places de stationnement")
NoteExercice 10
Lisser le nombre de places de stationnement pour les personnes à mobilité réduite (variable np_pmr).
SolutionSolution 10
sfCarLisse <-btb_smooth(pts = parkingsBuff[,c("np_pmr", "x", "y")], sEPSG ="2154",iCellSize = tcar, iBandwidth = rayon)# Filtrage des carreaux lissés dans Bordeaux centresfCarLisse <- sfCarLisse %>%st_join(centreBdx, left = F)%>%mutate(np_pmr = np_pmr * (1000/ tcar) ^2)# Carte lisséegenerCarte(sfCar = sfCarLisse, nomvar ="np_pmr", nbreaks =5, zone = centreBdx,titre ="Lissage des places de stationnement PMR")
Partie 2.4 : Lissage de ratios
NoteExercice 11
Lisser le nombre moyen de places de stationnement par parking.
Tip
Ne jamais lisser directement le ratio ! On lisse le numérateur et le dénominateur séparément. Puis, on fait le ratio sur les carreaux générés par btb_smooth.
SolutionSolution 11
sfCarLisse <-btb_smooth(pts = parkingsBuff[, c("nbObsLisse", "np_global", "x", "y")], sEPSG ="2154",iCellSize = tcar, iBandwidth = rayon)# Création du ratio lissé à partir des numérateur et dénominateur lisséssfCarLisse <- sfCarLisse %>%mutate(place_par_parking = np_global/nbObsLisse)sfCarLisse <- sfCarLisse %>%st_join(centreBdx, left = F)generCarte(sfCar = sfCarLisse, nomvar ="place_par_parking", nbreaks =5, zone = centreBdx,titre ="Lissage du nombre de places par parking")
NoteExercice 12
Lisser le taux de places de stationnement pour personnes à mobilité réduite (en %).
SolutionSolution 12
sfCarLisse <-btb_smooth(pts = parkingsBuff[, c("np_global", "np_pmr", "x", "y")], sEPSG ="2154",iCellSize = tcar, iBandwidth = rayon)# Création du ratio lissé à partir des numérateur et dénominateur lisséssfCarLisse$part_pmf <-100* sfCarLisse$np_pmr / sfCarLisse$np_globalsfCarLisse <- sfCarLisse %>%st_join(centreBdx, left = F)generCarte(sfCar = sfCarLisse, nomvar ="part_pmf", nbreaks =5, zone = centreBdx,titre ="Lissage de la part de places PMR")
Partie 2.5 [BONUS] : où trouver des places de parking pas chères ?
NoteExercice 13
Lisser le prix moyen d’une heure de stationnement par parking (sans pondérer par le nombre de places)
Tip
On veut lisser le prix d’une heure de stationnement par rapport au nombre de parkings.
SolutionSolution 13
sfCarLisse <-btb_smooth(pts = parkingsBuff[, c("nbObsLisse", "th_heur", "x", "y")], sEPSG ="2154",iCellSize = tcar, iBandwidth = rayon)sfCarLisse$prix_moyen <- sfCarLisse$th_heur / sfCarLisse$nbObsLissesfCarLisse <- sfCarLisse %>%st_join(centreBdx, left = F)generCarte(sfCar = sfCarLisse, nomvar ="prix_moyen", nbreaks =5, zone = centreBdx,titre ="Lissage du prix par parking (sans pondération)")
NoteExercice 14
Lisser le prix moyen d’une heure de stationnement (prendre en compte le nombre de places de stationnement par parking).
Tip
Pour chaque parking de la base, il faut lisser :
la multiplication du prix et du nombre de places
le nombre de places
Puis, faire le ratio pour obtenir le “prix moyen d’une place” lissé.
SolutionSolution 14
# Création de la variable "multiplication du prix et du nmbre de places" pour chaque parkingparkingsBuff <- parkingsBuff %>%mutate(prix_x_place = np_global * th_heur)sfCarLisse <-btb_smooth(pts = parkingsBuff[, c("np_global", "prix_x_place", "x", "y")], sEPSG ="2154",iCellSize = tcar, iBandwidth = rayon)# Et on rapporte par le nombre de places lissé.sfCarLisse <- sfCarLisse %>%mutate(prix_moyen_place = prix_x_place / np_global)sfCarLisse <- sfCarLisse %>%st_join(centreBdx, left = F)# Carte lisséegenerCarte(sfCar = sfCarLisse, nomvar ="prix_moyen_place", nbreaks =5, zone = centreBdx,titre ="Lissage du prix moyen par place de stationnement")
Phase 3 : Calcul d’indicateurs sur une zone à façon
NoteExercice 15
Combien d’habitants vivent dans le centre de Bordeaux tel que nous l’avons défini ?
Pour répondre à cette question :
Comme dans le tutoriel, charger la base des données Filosofi carroyées (grille de 200m) en ne chargeant que les carreaux de la Gironde (département 33) grâce à l’option query de st_read.
Vérifier les projections cartographiques utilisées puis faire une intersection géographique entre les carreaux de la Gironde et le contour géographique du centre de Bordeaux
Cartographier avec mapview les carreaux du centre de Bordeaux.
Calculer le nombre d’habitants grâce à la variable ind.
SolutionSolution 15
# 1. Chargement des données de Filosofi en Girondeurl_bucket <-"https://minio.lab.sspcloud.fr/projet-formation/r-lissage-spatial/"object ="carreaux_200m_met.gpkg"st_read_maison <-function(chemin_tab){ requete <-"SELECT idcar_200m, lcog_geo, ind, geom FROM carreaux_200m_met WHERE SUBSTR(lcog_geo, 1, 2) IN ('33')"st_read(chemin_tab, query = requete, quiet =TRUE)}car33 <-st_read_maison(paste0(url_bucket, object))# 2. Vérification de la projection head(car33)# projection 2154 (Lambert93)# Sélection des carreaux intersectant le centre de Bordeauxcarreaux_centreBdx <- car33 %>%st_join(centreBdx, left = F)# 3. Cartographie des carreaux du centre de Bordeauxmapview(centreBdx, color ="black", lwd =6, alpha.regions =0, legend = F) +mapview(carreaux_centreBdx, col.regions ="#ffff00")# 4. Combien d'habitants dans le centre de Bordeaux ?cat("Il y a approximativement", sum(carreaux_centreBdx$ind), "habitants dans le centre de Bordeaux")
mapview est un package de cartographie produisant des résultats proches de leaflet. Il est un peu plus rapide d’utilisation quant il s’agit de produire des résultats simples : notamment, il reprojette automatiquement les objets géographiques que vous souhaitez cartographier. Plus d’informations ici.↩︎
construit manuellement par les auteurs de ce tutoriel en utilisant le Geoportail.↩︎