Temps de trajet et matrices de distances avec R et OpenStreetMap

Le package osrm assure le lien entre R et l’API d’OSRM. OSRM est un service de routage basé sur les données OpenStreetMap.
Ce package permet d’obtenir le temps de trajet, la distance et le plus court chemin entre deux points via le réseau routier d’OpenStreetMap. Il est également possible d’obtenir des matrices de distances entre deux séries de points.

Voici un rapide aperçu des fonctions du package osrm :

  • osrmTable : Matrices de distances entre points.
  • osrmTableOD : Matrices de distances entre points où les origines et les destinations peuvent être différentes.
  • osrmViaRoute : Temps de trajet et distance routière entre deux points.
  • osrmViarouteGeom : Géométrie du plus court chemin entre deux points.

Par défaut le package utilise l’API publique d’OSRM (condition d’utilisation de l’API). Il est possible d’utiliser une autre instance du service si l’on veut en faire un usage intensif.

Voici un petit exemple de ce que l’on peut faire avec le package. Les cartes sont faites avec le le package cartography que j’ai déjà présenté ici.

L’idée dans cet exemple est de comparer l’accessibilité globale des communes de Loire-Atlantique à vol d’oiseau et par la route. Pour cela nous utiliserons l’indice d’accessibilité de Shimbel1 qui rapporte la somme des écarts de tous les sommets à la somme des écarts d’un sommet :
shishiSHi est l’indice de Shimbel pour la commune i et d(i,j) une mesure de distance entre i et j.

Chargement des données et des librairies
# Chargement des données
load("data/LoireAtlantique.RData")

# chargement des librairies
library(osrm)
library(rgeos)
library(cartography)

# création d'un data frame des communes avec leurs coordonées en WGS84
COM44.df <- data.frame(as.character(COM44.spdf$INSEE_COM), 
                       coordinates(spTransform(COM44.spdf, 
                                               CRSobj = 
                                                 "+init=epsg:4326")))
# renommer les colonnes
colnames(COM44.df) <- c("id", "x", "y")
Création de la matrice des distances euclidiennes

mateuclid <- rgeos::gDistance(COM44.spdf, byid = T)

Les 5 premières lignes et colonnes de mateuclid :

44148 44139 44221 44094 44125
44148 0.00 40163.20 29042.71 43736.88 78722.46
44139 40163.20 0.00 16747.42 37174.32 38623.89
44221 29042.71 16747.42 0.00 20492.02 60500.21
44094 43736.88 37174.32 20492.02 0.00 77979.86
44125 78722.46 38623.89 60500.21 77979.86 0.00

Nous venons de créer la matrice des distances euclidiennes (en mètres) entre les communes.

Création de la matrice des temps de trajets

Pour créer celle des distances routières nous pourrions utiliser la fonction osrmTable mais l’API public d’OSRM n’accepte pas les requêtes dépassant les 100 points. Nous allons donc utiliser la fonction osrmTableOD qui permet de combiner plusieurs requêtes.

# création d'une matrice distances routières
matroute <- osrmTableOD(dfo = COM44.df, 
                        ido = "id", xo = "x", yo = "y", 
                        dfd = COM44.df,
                        idd = "id", xd = "x", yd = "y")

Les 5 premières lignes et colonnes de matroute :

44148 44139 44221 44094 44125
44148 0.00 61.60 41.60 70.20 100.20
44139 61.80 0.00 30.10 51.40 53.70
44221 40.70 30.10 0.00 40.10 68.70
44094 70.20 49.80 38.40 0.00 79.30
44125 101.90 56.20 70.20 80.90 0.00

Les temps de trajet sont en minutes.

Calcul et cartographie des indices d’accessibilité de Shimbel

Nous calculons ensuite les indices de Shimbel à partir de ces deux matrices.

# Calcul d'indice d'accessibilité local d'ensemble
shimbel <- data.frame(id = COM44.df$id, 
                      ShimbelRoute = sum(matroute) / colSums(matroute), 
                      ShimbelEuclid = sum(mateuclid) / colSums(mateuclid))

Et nous pouvons ensuite cartographier ces indices, en commençant par l’accessibilité euclidienne.

# plot vide pour cadrer la carte
plot(COM44.spdf, col = NA, border = NA, bg = "#A6CAE0")
# plot du fond france
plot(FRA.spdf, add=T, col = "#E3DEBF", border = "#03779E")
# Index de Shimbel avec les distances euvclidiennes
choroLayer(spdf = COM44.spdf, spdfid = "INSEE_COM",
           df = shimbel, 
           var = 'ShimbelEuclid', nclass = 6, 
           legend.pos = "left",
           legend.title.txt = "Indice de\nShimbel",
           add=T)
# Ajout d'un habillage
layoutLayer(title = "Accessibilité euclidienne globale des communes de Loire-Atlantique", 
            sources = "T. Giraud, 2015", 
            author = "Fond de carte : GEOFLA 2015, IGN")

shimbEuclid

Plus une commune aura une position centrale dans le département plus son accessibilité sera forte.

# plot vide pour cadrer la carte
plot(COM44.spdf, col = NA, border = NA, bg = "#A6CAE0")
# plot du fond france
plot(FRA.spdf, add=T, col = "#E3DEBF", border = "#03779E")
# Index de Shimbel avec les distances euvclidiennes
choroLayer(spdf = COM44.spdf, spdfid = "INSEE_COM",
           df = shimbel, 
           var = 'ShimbelRoute', nclass = 6, 
           legend.pos = "left",
           legend.title.txt = "Indice de\nShimbel",
           add=T)
# Ajout d'un habillage
layoutLayer(title = "Accessibilité routière globale des communes de Loire-Atlantique",
            sources = "T. Giraud, 2015", 
            author = "Fond de carte : GEOFLA 2015, IGN ; Data (c) OpenStreetMap contributors ; Routes: OSRM. http://project-osrm.org/")

shimbRoute
L’accessibilité des communes via le réseau routier est plus nuancée que la simple accessibilité euclidienne (en cercles concentriques).

Calcul de l’efficacité routière

Pour mesurer l’efficacité du réseau routier nous pouvons faire le rapport entre les deux indices. Nous utilisons le fond OSM-transport comme fond de carte pour confronter cette efficacité avec le réseau routier qui sous-tend les mesures d’accessibilité routière.

# calcul du rapport entre les deux indices
shimbel$eff <-  shimbel$ShimbelRoute/shimbel$ShimbelEuclid

# obtension d'une tuile osm-transport sur le departement
# avec la fonction getTiles de cartography
tiles44 <- getTiles(spdf = COM44.spdf, type = "osm-transport")

## affichage de la carte
# plot vide pour cadrer la carte
plot(COM44.spdf, col = NA, border = NA)
# plot du fond de carte osm-transport
tilesLayer(tiles44, add=T)
# Index de Shimbel avec les distances euvclidiennes
choroLayer(spdf = COM44.spdf, spdfid = "INSEE_COM",
           df = shimbel, 
           var = 'eff', 
           breaks = c(min(shimbel$eff),
                      0.8,0.9,0.95, 1/0.95, 1/0.9, 
                      max(shimbel$eff)),
           col = carto.pal(pal1 = "green.pal",3, 
                           "wine.pal",2, 
                           transparency = T, 
                           middle = T),
           lwd = 0.2,
           legend.pos = "left",
           legend.title.txt = "Efficacité",
           legend.frame = TRUE,
           legend.values.rnd = 2,
           add=T)

# Ajout d'un habillage
layoutLayer(title = "Efficacité du réseau routier des communes de Loire-Atlantique", 
            sources = "T. Giraud, 2015", 
            author = "Fond de carte : OpenStreetMap contributors ; Routes: OSRM. http://project-osrm.org/")

rapport
Les communes les plus périphériques sont favorisées par le réseau routier, elle sont desservies par des voies rapides qui améliorent leur accessibilité. Certaines communes plus centrales sont au contraire moins accessibles que ce que l’on pourrait imaginer. Cela est sûrement dû, pour certaines, à leur position au bord de la Loire qui implique des détours pour emprunter les quelques ponts qui enjambent le fleuve.

Quelques trajets routiers

Pour illustrer le contournement de la Loire nous pouvons afficher quelques trajets à partir de la commune la moins accessible avec la fonction osrmViarouteGeom.
route

L’ensemble du code et des données utilisées ici est disponible sur GitHub, tout comme la version de développement du package.

1. Pumain Denise, Saint-Julien Thérèse (1997), L’analyse spatiale. Localisations dans l’espace. Paris, Armand Colin.(p110)


7 réflexions au sujet de « Temps de trajet et matrices de distances avec R et OpenStreetMap »

  1. Bonjour,

    Merci pour votre tuto qui est d’une grande aide. Petit problème avec la fonction osrmTableOD qui me renvoi « impossible de trouver la fonction « osrmTableOD » ». Je ne trouve rien sur cette fonction sur internet… Pouvez-vous m’aidez?

    Merci,
    Coralie

  2. Bonjour comment fait-on pour obtenir le Rdata ?
    Je dois faire une matrice de distance pour le loiret.

    merci

    1. Bonjour,
      Les fichiers .RData sont des fichiers contenant des objets R.
      Dans cet exemple le fichier LoireAtlantique.RData contient deux objets : COM44.spdf qui est un SpatialPolygonsDataFrame des communes de Loire-Atlantique et FRA.spdf qui est un SpatialPolygonsDataFrame du contour de la France. Ces deux fichiers sont utiles pour créer les cartes et pour obtenir les coordonnées des centroides des communes.
      Ce sont ces coordonnées, stockées dans une data.frame, qui sont utilisées pour effectuer les calculs de distance avec les fonctions du package osrm.
      Pour calculer une matrice de distance vous n’aurez besoin que d’un data.frame contenant au moins trois colonnes (identifiant des communes, longitude et latitude en WGS84). Il vous faut donc créer un fichier contenant ces identifiants et coordonnées et l’importer dans R, vous n’avez pas forcément besoin de stocker ces données en RData.
      Bien à vous,
      Timothée

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *