Avant toute diffusion auprès des partenaires, il faut bien veiller à respecter :
le secret
primaire
secondaire
fiscal
les conventions établies avec les fournisseurs des données
Qualité des cartes
Pour simplifier : on prend des libertés avec la sémiologie cartographique
Auteur : Timothée Giraud, auteur de la librairie mapsf
Système de projection
Nom
Description
Code EPSG
Lambert93
Système de projection officiel pour la métropole
2154
LAEA
Système de projection européen
3035
WGS84
GPS (utile pour utiliser Leaflet)
4326
2. Configurations
2.1 Chargement des librairies
Cinq librairies principales sont nécessaires pour ce TP :
sf pour manipuler des fichiers spatiaux (importer des .shp, transformer des projections, et réaliser des géotraitements) ;
mapsf pour réaliser des cartes dans RStudio ;
mapview (reposant sur leaflet) pour réaliser des cartes interactives (fond de carte OpenStreetMap);
btb pour le carroyage et lissage ;
dplyr pour le traitement des données, en particulier l’agrégation géographique.
Charger les librairies nécessaires
## Liste des librairies utiliséespackages <-c("dplyr", "sf", "mapsf", "leaflet", "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, quiet =TRUE)library(x, character.only =TRUE) } })
Sur le SSPCloud :
Utiliser le package aws.s3 pour charger les données stockées dans Minio ;
2.3 Chargement et préparation des données cartographiques
Fond de carte du territoire à étudier [Chargement]
Chargement de la couche vectorielle des départements de la petite couronne parisienne.
Type de fichiers : .shp ou .gpkg (format recommmandé, voir ici)
# Récupération du fond de carte grâce à sf::st_readchemin_file <-paste0(url_bucket, bucket, "/r-lissage-spatial/depCouronne.gpkg")depCouronne_sf <- sf::st_read(chemin_file)
Reading layer `depCouronne' from data source
`https://minio.lab.sspcloud.fr/projet-formation/r-lissage-spatial/depCouronne.gpkg'
using driver `GPKG'
Simple feature collection with 4 features and 4 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 637307.1 ymin: 6843303 xmax: 671686 ymax: 6879253
Projected CRS: RGF93 v1 / Lambert-93
Fond de carte du territoire à étudier [Visualisation]
On crée une zone tampon (buffer) autour du territoire d’intérêt, avec une marge (ici 2 000m), sous la forme d’un objet sf vectoriel ;
buffer_sf <-st_buffer(paris_sf, dist =2000)
Remarque: Pour la zone tampon, prendre une marge légèrement plus grande que le rayon de lissage envisagé.
Méthode 2 : sélection géométrique [3/4]
On repère les observations comprises dans cette zone tampon par intersection géographique.
sfBase_filtre <-st_join(sfBase, buffer_sf, left =FALSE)head(sfBase_filtre, 2)
Simple feature collection with 2 features and 7 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: 646929.9 ymin: 6864730 xmax: 648001.8 ymax: 6866153
Projected CRS: RGF93 v1 / Lambert-93
id_mutation date_mutation type_local nombre_pieces_principales
3 2021-447025 2021-01-08 Appartement 3
5 2021-447029 2021-01-05 Appartement 2
valeur_fonciere surface_reelle_bati nom geometry
3 384000 41 territoire POINT (648001.8 6866153)
5 407200 24 territoire POINT (646929.9 6864730)
Méthode 2 : sélection géométrique [4/4]
Zone, buffer et 2000 points tirés aléatoirement dedans.
code du schema explicatif des zones selectionnées
# Mise en forme de la couche bufferbuffer_sf$nom <-"buffer"# Échantillon de 2000 observations dans le buffersfBase_sample <- sfBase_filtre[sample(1:nrow(sfBase_filtre), 2000), ]# Cartographie pédagogique avec mapviewmapview(paris_sf, col.regions ="#26cce7") +mapview(buffer_sf %>%st_cast("MULTILINESTRING"), color ="#FFC300", lwd =6) +mapview(sfBase_sample, #col.regions = "black",alpha.regions=0.5,alpha =0, cex =2)
2.4 Carroyage de données
Les étapes du carroyage [1/7]
Avant de lisser les données ponctuelles, on peut souhaiter représenter ces données sous forme carroyée afin de se les approprier.
➡️ Le carroyage nécessite plusieurs étapes
Les étapes du carroyage [2/7]
Associer chaque point (= vente géolocalisée) au centroïde du carreau auquel il appartient (btb_add_centroids).
➡️ Le territoire est découpé en carreaux de 200 mètres à partir de l’origine du référentiel.
iCellSize =200# Carreaux de 200m# On repart de la base filtrée selon la première méthodepoints_carroyage <- btb::btb_add_centroids(pts = dfBase_filtre,iCellSize = iCellSize)
Le carroyage permet d’avoir un premier aperçu des données le plus fidèle à la réalité.
Il est également utilisé pour simplifier les données avant lissage afin de rendre le calcul de lissage moins long en cas de très grand nombre d’observations.
3. Lissage
3.1 Calcul de densité
Lissage le plus simple à réaliser
Densité = Quantité par unité de surface (un carreau)
Ici : densité de ventes de logements dans la ville de Paris au cours de l’année 2021
☠️ Effets de bord
Toujours pour éviter les effets de bord :
Lissage sur une zone plus large que la zone d’intérêt
➡️ Utilisation de dfBase_filtre (construite précédemment).
Création une variable nbObsLisse
On crée la variable nbObsLisse = 1 pour chaque observation
# Variable à lisser = nombre d'observations = nombre de ventesdfBase_filtre$nbObsLisse <-1head(dfBase_filtre, 2)
➡️ On lissera ensuite la variable nbObsLisse avec la fonction btb::btb_smooth
Lissage et enregistrement dans sfCarrLiss
Paramètres de btb_smooth
pts : le tableau des données à lisser. Il doit nécessairement contenir une colonne x, une colonne y, et 1 à n colonnes numériques (variables à lisser) ;
sEPSG : chaîne de caractères indiquant le code epsg du système de projection utilisé ;
iCellSize : un entier indiquant la taille des carreaux ;
iBandwidth : un entier indiquant le rayon de lissage.
Représentation cartographique de la densité lissée
Carte choroplèthe ;
Discrétisation quantile de la densité lissée ;
Avec 5 classes de carreaux (5 couleurs) .
code
# Filtrage des carreaux lissés intersectant la ville de ParissfCarrLiss_paris <- sfCarrLiss %>%st_join(paris_sf[, "geometry"], left =FALSE)# Carte lisséemf_init(x = sfCarrLiss_paris)mf_map(x = sfCarrLiss_paris, type ="choro",var ="nbObsLisse",breaks ="quantile",nbreaks =5,lwd =1,add =TRUE)mf_map(x = contourParis, lwd =4,col ="black", add =TRUE)mf_layout(title ="Lissage avec rayon de 400m",credits ="Insee-DSAU, DGFiP, Etalab, IGN, mapsf")
Récapitulatif : lissage de densité
On souhaite obtenir le nombre de ventes lissé, en 2021 dans Paris intramuros :
On sélectionne les ventes au-delà de Paris intramuros (effets de bord)
On lisse grâce à btb_smooth
On obtient une grille carroyée bien plus vaste que Paris intramuros
On filtre uniquement les carreaux dans Paris
On cartographie la variable lissée (nbObsLissee)
Faire varier le rayon de lissage
Taille optimale du rayon de lissage ?
Rayon grand (1km) : aspects structurels des données
Rayon petit (600m) : spécificités locales des données.
➡️ Compromis à faire par le statisticien géographe entre précision et généralisation (connaissance des données et objectifs recherchés)
Faire varier le rayon de lissage (600m)
code lissage
dataLissage <- dfBase_filtre[, c("nbObsLisse", "x", "y")]sfCarrLiss <- btb::btb_smooth(pts = dataLissage, sEPSG ="2154",iCellSize =200, iBandwidth =600)# Filtrage des carreaux lissés dans ParissfCarrLiss_paris <- sfCarrLiss %>%st_join(paris_sf[, "geometry"], left =FALSE)
code carto
# Carte lisséemf_init(x = sfCarrLiss_paris)mf_map(x = sfCarrLiss_paris, type ="choro",var ="nbObsLisse",breaks ="quantile",nbreaks =5,lwd =1,add =TRUE)mf_map(x = contourParis, lwd =4,col ="black", add =TRUE)mf_layout(title ="Lissage avec rayon de 600m",credits ="Insee-DSAU, DGFiP, Etalab, IGN, mapsf")
Faire varier le rayon de lissage (1000m)
code lissage
dataLissage <- dfBase_filtre[, c("nbObsLisse", "x", "y")]sfCarrLiss <- btb::btb_smooth(pts = dataLissage, sEPSG ="2154",iCellSize =200, iBandwidth =1000)# Filtrage des carreaux lissés dans ParissfCarrLiss_paris <- sfCarrLiss %>%st_join(paris_sf[, "geometry"], left =FALSE)
code carto
# Carte lisséemf_init(x = sfCarrLiss_paris)mf_map(x = sfCarrLiss_paris, type ="choro",var ="nbObsLisse",breaks ="quantile",nbreaks =5,lwd =1,add =TRUE)mf_map(x = contourParis, lwd =4,col ="black", add =TRUE)mf_layout(title ="Lissage avec rayon de 1000m",credits ="Insee-DSAU, DGFiP, Etalab, IGN, mapsf")
Faire varier le rayon de lissage (1000m)
Sans grille apparente !
code carto
mf_init(x = sfCarrLiss_paris)mf_map(x = sfCarrLiss_paris, type ="choro",var ="nbObsLisse",breaks ="quantile",nbreaks =5,border =NA, # C'est ici que ça se passe# lwd=1,add =TRUE)mf_map(x = contourParis, lwd =4,col ="black", add =TRUE)mf_layout(title ="Lissage avec rayon de 1000m, sans grille",credits ="Insee-DSAU, DGFiP, Etalab, IGN, mapsf")
# Calculer le tauxsfCarLiss$prixMoyen <- sfCarLiss$valeur_fonciere / sfCarLiss$nbObsLisse# CartographiesfCarLiss_paris <- sfCarLiss %>%st_join(paris_sf, left =FALSE)mf_init(x = sfCarLiss_paris)mf_map(x = sfCarLiss_paris, type ="choro",var ="prixMoyen",breaks ="quantile",nbreaks =5,border =NA,leg_val_rnd =1, add =TRUE)mf_map(x = contourParis, lwd =4,col ="black", add =TRUE)mf_layout(title ="Lissage des prix de vente avec un rayon de 800m",credits ="Insee-DSAU, DGFiP, Etalab, IGN, mapsf")
3.3 Calcul de taux
Taux de grands logements
Proportion de ventes comportant plus de 4 pièces principales ?
indicatrice quatrePieces
lissage numérateur et dénominateur
calcul taux
intersection géographique avec Paris
code
# Creation indicatrice quatrePiecesdfBase_filtre$quatrePieces <-ifelse( dfBase_filtre$nombre_pieces_principales >=4, 1, 0)# Lissage des variables `quatrePieces` et `nbObsLisse`dataLissage <- dfBase_filtre[,c("nbObsLisse", "quatrePieces", "x", "y")]sfCarLiss <- btb::btb_smooth(pts = dataLissage, sEPSG ="2154",iCellSize =100, iBandwidth =800)# Calculer le tauxsfCarLiss$txQuatrePieces <- sfCarLiss$quatrePieces / sfCarLiss$nbObsLisse# Intersection géographique avec ParissfCarLiss_paris <- sfCarLiss %>%st_join(paris_sf, left =FALSE)# Cartomf_init(x = sfCarLiss_paris)mf_map(x = sfCarLiss_paris, type ="choro",var ="txQuatrePieces",breaks ="quantile",nbreaks =5,border =NA,leg_val_rnd =1, add =TRUE)mf_map(x = contourParis, lwd =4,col ="black", add =TRUE)mf_layout(title ="Logements avec 4 pièces ou plus (rayon de 800m)",credits ="Insee-DSAU, DGFiP, Etalab, IGN, mapsf")
➡️ Carte similaire à la carte des prix moyens
➡️ Lissage du prix au mètre-carré
Prix au m²
Il faut lisser séparément les prix de vente (numérateur) et le nombre de mètres-carrés (dénominateur).
Si on lisse le prix au m² de chaque logement vendu, on sur-pondère artificiellement les prix au m² des petits logements (car l’unité statistique devient alors le logement, et non le m² vendu).
code lissage
dataLissage <- dfBase_filtre[, c("surface_reelle_bati", "valeur_fonciere", "x", "y")]sfCarLiss <- btb::btb_smooth(pts = dataLissage,sEPSG ="2154",iCellSize =100,iBandwidth =800)# Calculer le prix au m²sfCarLiss$prixM2 <- sfCarLiss$valeur_fonciere / sfCarLiss$surface_reelle_bati
Calculons le nombre et le prix moyen des transactions immobilières en 2021 dans le triangle d’or 1.
Import et visualisation de la zone à façon « Triangle d’or ». Ce fichier géographique est au format .kml et se lit sans problème avec la fonction sf::st_read.