Accessibilité et données OpenStreetMap
Accessibilité et données OpenStreetMap : Exemple pratique sur les maternités de la Nièvre et de la Seine-St-Denis
Accessibilité et données OpenStreetMap
Ce document présente l’ensemble d’une chaîne de traitement reproductible qui porte sur la thématique de l’accessibilité aux maternités. Les données sont successivement importées, traitées, analysées et représentées. Cette chaîne de traitement peut être reproduite pour deux départements de la France métropolitaine: la Nièvre (58) et la Seine-St-Denis (93). l’ensemble des étapes sont réalisées sous R, à partir de données en libre accès (IGN, INSEE, et OpenStreetMap). Ce travail a été réalisé et présenté dans le cadre d’un séminaire commun aux axes “Territoires et Santé et”Information Territoriale locale" de la Fédération de Recherche CIST, organisé le 12 Juin 2019 à l’Université de Paris.
— T. Giraud (CNRS, UMS RIATE), R. Ysebaert (Université de Paris, UMS RIATE) & H. Pecout (CNRS, FR CIST)
Certains des traitements présentés dans ce document s’avèrent coûteux en performance ou dépendant de l’utilisation d’un serveur distant. Nous vous proposons donc de télécharger ce dossier contenant certaines données générées dans le code présenté ci-dessous et un projet Rstudio. Cela vous facilitera la reproduction de l’ensemble des analyses et des représentations graphiques présentées dans ce document.
Les packages
L’installation de certaines bibliothèques est nécessaire pour réaliser l’ensemble de cette chaîne de traitement :
# Depuis le CRAN
install.packages(c("readxl",
"sf",
"SpatialPosition",
"osmdata",
"osrm",
"banR",
"ggplot2",
"cartography",
"remotes"))
# Depuis Github (librarie en dévelopement)
remotes::install_github("jimhester/archive")Une grande partie de ces bibliothèques sont spécialisées dans la gestion, l’analyse et la représentation de l’information géographique.
# library(readxl) : Import/export de fichier Excel
# library(archive) : Décompresser une archive (fichier.7z)
# library(sf) : Gestion de données spatiales + géotraitement
# library(SpatialPosition) : Analyse spatiale
# library(osmdata) : Télécharger et utiliser des données OpenStreetMap
# library(osrm) : Utiliser l'API OSRM (service de routage à partir des données osm)
# library(banR) : Utiliser l'API BAN (Base Adresses Nationale) pour le géocodage
# library(ggplot2) : Représentation graphique
# library(cartography) : Cartographie
# library(remotes) : Télécharger et installer un package stocké sur un dépot (git)
Les données
Pratiquement la totalité des données utilisées sont disponibles en accès libre sur internet. Nous allons ainsi commencer par les récupérer automatiquement en langage R.
1. Info. géo. conventionnelle
Nous téléchargeons la BD ADMIN EXPRESS (2018) fournie par l’IGN. Cette base de données comporte les couches géographiques des principaux découpages administratifs français.
# Url de la BD Admin Express mise à disposition par l'IGN
url <- "ftp://Admin_Express_ext:Dahnoh0eigheeFok@ftp3.ign.fr/ADMIN-EXPRESS_2-0__SHP__FRA_2019-03-14.7z.001"
# Création d'un nom de fichier temporaire
tf <- tempfile()
# Téléchargement de la BD admin Express de l'IGN
download.file(url, tf , mode = "wb" )
# Décompression de l'archive dans le répertoire data-raw
library(archive)
archive_extract(archive(path = tf), dir="data-raw")2. Données démographiques
Nous récupérons ensuite des données fournies par l’INSEE à l’échelle communale sur la population par tranches d’âge quinquennal et par sexe. Il s’agit de données harmonisées (1968-2015) issues des recensements de la population.
# Url du fichier (Recensements harmonisés - Séries départementales et communales)
url_2 <- "https://www.insee.fr/fr/statistiques/fichier/1893204/pop-sexe-age-quinquennal6815.zip"
# Création d'un nom de fichier temporaire
tf <- tempfile()
# Téléchargement du fichier INSEE
download.file(url_2, tf , mode = "wb" )
# Décompression du ZIP dans le répertoire data-raw
unzip(zipfile="data-raw/IRIS_2015_data.zip", exdir = "data-raw")3. Liste des maternités
Les principaux traitements réalisés reposent sur des calculs d’accessibilité à une infrastructure de santé : les maternités. Il est donc nécessaire de disposer d’une liste de ces infrastructures (et de leurs adresses) pour nos deux territoires d’intérêt : les départements de la Nièvre (58) et de la Seine-St-Denis (93).
Il s’agit bien évidemment d’une donnée accessible à tout le monde, mais aucun organisme ne semble la fournir de façon compilée. Nous avons donc constitué ces listes à partir de différentes sources (ex : Journal des femmes), et mises à disposition sur un dépôt :
- Liste des Maternités de la Nièvre (et des alentours) -> mater_58.csv
- Liste des Maternités de la Seine-St-Denis (et des alentours) -> mater_93.csv
Vous retrouverez également ces deux fichiers dans le projet Rstudio mis à disposition pour reproduire facilement toute la chaîne de traitement
Attention, ces listes n’ont pas la prétention d’être exhaustives et de refléter parfaitement la réalité, elles ont avant tout été élaborées dans l’objectif de rendre les analyses présentées comme plausibles.
Ex : Liste des maternités de la Nièvre (mater_58.csv) :
4. Données OpenStreetMap
La majorité des analyses effectuées repose sur l’utilisation de la plus grande base libre de données géographiques au Monde : OpenStreetMap. Nous allons utiliser cette base pour 3 opérations différentes :
- Extraction de données OSM (routes) à l’aide du package
osmdatapour habiller les représentations cartographiques.
- Utilisation du package
osrmpour calculer des matrices distance-temps entre deux groupes de points
- Utilisation du package
osrmpour extraire les plus courts chemins entre deux groupes de points.
L’API d’OpenStreetMAp permet d’utiliser et d’interroger la base de données sans avoir à récupérer de données localement.
Pré-traitements
Avant de démarrer les analyses, il est nécessaire de préparer les données brutes téléchargées. Dans un premier temps, nous allons ainsi sélectionner, extraire, géocoder des données et créer de nouvelles variables.
L’ensemble de la chaîne de traitement fonctionne autant pour le département de la Nièvre (58) que pour celui de la Seine-St-Denis (93). Mais le code présenté dans le document est optimisé pour le territoire de la Nièvre. Il sera donc nécessaire d’apporter de légères modifications (discrétisation, unités, portée des lissages…) pour l’adapter au mieux au territoire de la Seine-St-Denis (cf. dernière partie).
Géocodage des maternités
Pour géolocaliser les adresses des différentes maternités recensées, nous utiliserons la bibliothèque de géocodage banR, qui repose sur la Base Adresses Nationale constituée par plusieurs producteurs de données : La Poste, l’IGN, la DGFiP, OpenstreetMap France, et la mission Etalab (service du Premier Ministre chargé de l’Open Data en France). Il s’agit de la meilleure base de données (et donc du meilleur package) pour géocoder des adresses en France.
### CHOIX DE LA ZONE D'ETUDE : Nièvre ou Saine-Saint-Denis ? 58 ou 93 ?
# dpt <- "93"
dpt <- "58"
# Import du fichier des maternités de la nièvre (et alentours)
maternite <- read.csv(paste0("data-raw/mater_",dpt,".csv"), encoding = "UTF-8")
# Formatage des adresses
maternite$Full_adresse <- paste0(maternite$ADRESSE, ", ", maternite$COMMUNE)
# GEOCODAGE des maternités
library(banR)
maternite <- geocode_tbl(maternite,
adresse = Full_adresse,
code_postal = CP)La fonction geocode_tbl() permet de récupérer une longitude et une latitude à partir d’une adresse postale :
A partir des longitudes et latitudes récupérées, nous pouvons construire une couche géographique de points.
# Chargament de la library sf
library(sf)
# tranformation du tableau en objet SF (point) à partir des longitudes/latitudes
maternite_sf <- st_as_sf(data.frame(maternite), coords = c("longitude", "latitude"), crs = 4326)
# Puis on ne garde que les variables pertinentes
maternite_sf <- maternite_sf[,c("ID", "NOM", "COMMUNE", "NIVEAU", "FERME")]
# Caractéristique de l'objet sf créé
maternite_sf## Simple feature collection with 21 features and 5 fields
## geometry type: POINT
## dimension: XY
## bbox: xmin: 1.896772 ymin: 46.46508 xmax: 5.065187 ymax: 47.90172
## epsg (SRID): 4326
## proj4string: +proj=longlat +datum=WGS84 +no_defs
## First 10 features:
## ID NOM COMMUNE NIVEAU
## 1 1 Centre hospitalier d’Avallon Avallon 1
## 2 2 Centre hospitalier de Clamecy Clamecy 1
## 3 3 Centre hospitalier de Cosne Cours sur Loire Cosne-Cours-sur-Loire 1
## 4 4 Centre hospitalier de Decize Decize 1
## 5 5 Hôpital Pierre Beregovoy Nevers 2
## 6 6 Centre hospitalier de Moulins Moulins 2
## 7 9 Centre hospitalier de Saint-Amand - Montrond Saint-Amand-Montrond 1
## 8 10 Centre hospitalier de Vierzon Vierzon 1
## 9 11 Hôpital privé Guillaume de Varye Saint-Doulchard 1
## 10 12 Centre hospitalier Jacques Coeur Bourges 2
## FERME geometry
## 1 2003 POINT (3.905244 47.4899)
## 2 2008 POINT (3.508865 47.45345)
## 3 2018 POINT (2.927963 47.40477)
## 4 2010 POINT (3.452116 46.82248)
## 5 NA POINT (3.123394 46.97967)
## 6 NA POINT (3.325008 46.57065)
## 7 NA POINT (2.495952 46.72525)
## 8 NA POINT (2.052123 47.22765)
## 9 NA POINT (2.356531 47.10646)
## 10 NA POINT (2.437346 47.08396)
Nos maternités se présentent dorénavant sous la forme de points géolocalisés dans l’espace (couche géographique = objet sf) :
Données géographiques
Dans un premier temps, nous ne chargeons que les couches géographiques, proposées par la BD ADMIN EXPRESS, qui nous intéressent : le découpage communal et départemental français.
# Chargament de la librairie sf
library(sf)
# Récupération de la couche géographique des communes françaises
com_fr <- st_read('data-raw/ADMIN-EXPRESS_2-0__SHP__FRA_2019-03-14/ADMIN-EXPRESS/1_DONNEES_LIVRAISON_2019-03-14/ADE_2-0_SHP_LAMB93_FR/COMMUNE.shp', quiet=TRUE)
# Récupération de la couche géographique des départements français
dep_fr <- st_read('data-raw/ADMIN-EXPRESS_2-0__SHP__FRA_2019-03-14/ADMIN-EXPRESS/1_DONNEES_LIVRAISON_2019-03-14/ADE_2-0_SHP_LAMB93_FR/DEPARTEMENT.shp', quiet=TRUE)# Affichage des couches
par(mar=c(0,0,0,0))
plot(st_geometry(com_fr), border="grey60", lwd=0.1)
plot(st_geometry(dep_fr), border="grey25", lwd=0.3 , add=TRUE)a. Délimitation de la zone d’étude
Nous n’avons pas besoin de garder les délimitations de l’ensemble du territoire métropolitain. Seules les limites communales et départementales de l’environnement de nos maternités nous seront utiles :
# 1) On applique la projection lambert 93 aux maternités (géotraitements !)
# lambert 93 -> epsg:2154 = Projection officielle francaise
maternite_sf <- st_transform(maternite_sf, crs = st_crs(com_fr))
# 2) On récupère le x et y min/max de la couche géographique des maternités avec un
# buffer de 5000 mètres
StudyArea <- st_sf(st_as_sfc(st_bbox(st_buffer(maternite_sf, 5000))))
# 3) Découpage du fond de carte communale/departementale à partir de l'emprise calculée
COM <- st_intersection(x = com_fr, y = StudyArea)
DEP <- st_intersection(x = dep_fr, y = StudyArea)Le code ci-dessus permet de créer une couche géographique des limites communales, uniquement pour notre zone d’étude (localisation des maternités). Nous obtenons ainsi une sélection des couches géographiques fournies par l’IGN :
par(mar=c(0,0,0,0))
plot(st_geometry(StudyArea), border="gold1", lwd=2)
plot(st_geometry(DEP[DEP$INSEE_DEP==dpt,]), col="grey90", border=NA, add=TRUE)
plot(st_geometry(COM), border="grey60", lwd=0.2, add=TRUE)
plot(st_geometry(DEP), border="grey30", lwd=0.5, add=TRUE)
plot(st_geometry(maternite_sf), col="darkslategray4", pch=15, add=TRUE)b. Extraction de données OSM
La bibliothèque osmdata permet de télécharger des données OpenStreetMap et de les charger comme objet sf sous R. Nous allons ainsi procéder à l’extraction du réseau routier principal de notre zone d’étude pour habiller nos représentations cartographiques à venir.
# Récupération de l'emprise spatiale des communes du département
# bbox = c(xmin, ymin, ymax, ymin)
bbox <- st_bbox(st_transform(StudyArea,4326))
# Construction requête (emprise + timeout) principale
library(osmdata)
q <- opq(bbox = bbox , timeout = 5000)
# Construction de trois requêtes, pour extraire 3 types de routes
q1 <- add_osm_feature(q, key = 'highway', value = 'primary', value_exact = FALSE)
q2 <- add_osm_feature(q, key = 'highway', value = 'motorway', value_exact = FALSE)
q3 <- add_osm_feature(q, key = 'highway', value = 'trunk', value_exact = FALSE)
# Extraction des routes 'primary' (OSM -> objet sf)
roads1 <- osmdata_sf(q1)$osm_lines
# Extraction des routes 'motorway'
roads2 <- osmdata_sf(q2)$osm_lines
# Extraction des routes 'trunk'
roads3 <- osmdata_sf(q3)$osm_lines
# Fusion des 3 objets sf crées
roads <- c(st_geometry(roads1), st_geometry(roads2), st_geometry(roads3))
# Projection de 'roads' = projection lambert93
roads <- st_transform(roads, st_crs(StudyArea))
# Découpage du réseau routier par la "study area"
roads <- st_intersection(x = roads, y = StudyArea)Affichage du réseau routier extrait de la base de données OpenStreetMap :
# Affichage du réseau routier extrait
par(mar=c(0,0,0,0))
plot(st_geometry(StudyArea), border=NA)
plot(st_geometry(DEP[DEP$INSEE_DEP==dpt,]), col="grey90", border=NA, add=TRUE)
plot(st_geometry(COM), border="grey60", lwd=0.2, add=TRUE)
plot(st_geometry(DEP), border="grey30", lwd=0.5, add=TRUE)
plot(roads, col="red4", lwd=0.7, add=T)
plot(st_geometry(StudyArea), border="gold1", lwd=2, add=TRUE)
plot(st_geometry(maternite_sf), col="darkslategray4", pch=15, add=TRUE)Données démographiques
Le fichier source de l’INSEE couvre l’ensemble des communes de la France métropolitaine, caractérisées par 45 variables. Nous allons uniquement garder les données couvrant notre zone d’étude et les variables que nous souhaitons utiliser.
a. Nombre de femmes en âge de procréer par communes
# Chargement de "readxl"
library(readxl)
# Lecture du fichier INSEE
data_INSEE <- read_excel("data-raw/pop-sexe-age-quinquennal6815.xls",
sheet = "COM_2015",
skip = 13)
# Construction d'un nouveau tableau de données à partir du fichier INSEE
# Calcul de deux nouvelles variables (Nb_F_1549 et Pop_Total_2015)
Com_Pop <-data.frame(INSEE_COM=paste0(data_INSEE$DR, data_INSEE$CR),
Nb_F_1549 = round(data_INSEE$ageq_rec04s2rpop2015 +
data_INSEE$ageq_rec05s2rpop2015 +
data_INSEE$ageq_rec06s2rpop2015 +
data_INSEE$ageq_rec07s2rpop2015 +
data_INSEE$ageq_rec08s2rpop2015 +
data_INSEE$ageq_rec09s2rpop2015 +
data_INSEE$ageq_rec10s2rpop2015,0),
Pop_Total_2015 = round(rowSums(data_INSEE[7:46], na.rm = TRUE),0))Le code ci-dessus permet de calculer deux nouvelles variables :
- Le nombre de femmes de 15 à 49 ans par commune, en 2015
- La population totale par commune, en 2015