L’objectif de ce projet informatique est de se servir de données libres sur la ville de Bordeaux pour faire des analyses descriptives et des prédictions. On va s’intéresser aux données spatiales et temporelles fournies par des capteurs de traffic disposés tout au long de la ville.
Bordeaux Métropole dispose actuellement de 500 capteurs dans leur territoire qui journalièrement comptent le nombre de voitures qui passent à un point géographique donné. Cette information est importante, d’une part, pour la mairie mais aussi pour les citadins.
Dans un premier temps on parlera des difficultés encontrées lors de la récuperation des données en temps réel. Ensuite, on s'intéressera aux données founies par la CUB sur les capteurs au formats .csv, et on fera des analyses statistiques sur les capteurs. Pour finir, une partie sur le web crawling sera dévelopée avec notamment un exemple sur un site de thèses.
La première phase d'un tel projet est la récupération des données, celle-ci représentera pour nous le plus gros challenge. En effet, les donnnées des capteurs de traffic sont proposées sous le format ".wps": Web Processing Service. Il s'agit d'un format d'interface permettant de faire appel à des services de traitement.
Dans un premier temps, afin de mieux comprendre, nous utilisons ces données sous le language conseillé javascript. Grâce aux tutoriaux de la page Web de la CUB, nous parvenons à ouvrir une carte (en fond) et à placer les capteurs de trafic par dessus (layer).
Nous comprenons que l'objectif du format .wps est de pouvoir s'intégrer facilement dans n'importe quelle page web et adapter l'API selon les couches souhaitées. Après de nombreux essais, on ne peux pas obtenir facilement ces donnes: l'accés semble restreint pour les novices en informatique.
En définitive, on reussit à afficher les données ici mais pas à récupérer la matrice des données.
On abandonne les données en temps réel et on se limite donc aux fichier .csv sur les capteurs qui sont aussi présents sur le site. On trouve 6 fichiers pour les années de 2010 à 2015.
On remarque que dans le fichier 2010 on a aussi les colonnes pour l'année 2009, donc on peut dire qu'on a 7 années à disposition.
Pour chaque année, on dispose de 4 données par capteur:
-l'identifiant du capteur: du type "Z05BS" par exemple
-HPM: le nombre de voitures à l'Heure de Pointe le Matin (7h30-8h30)
-HPS: le nombre de voitures à l'Heure de Pointe le Soir (17h-18h)
-MJO: la Moyenne par Jours Ouvrés, correspondant au débit moyen en véhicule/heure sur les jours ouvrés
Les données sur les poids lourds sont enlevées (renseignées pour seulement 100 données) et les pourcentages d'évolution aussi (redondance des informations).
head(trafic_2009)
## Capteur HPM.2009 HPS.2009 MJO.2009
## 1 Z05Ae 171 200 2284
## 2 Z05As 729 1070 12588
## 3 Z05Be 677 573 7909
## 4 Z05Bs 446 859 8031
## 5 Z06Ae 753 709 8620
## 6 Z06As 503 553 6590
Une fois les NA enlevés, on remarque que le nombre de lignes (=nombre de capteurs) des fichiers varie selon les années. En effet, il oscille entre 466 et 523. On ne veut garder que les capteurs qui sont renseignés pour chaque année, on fait un merge par Capteurs et on obtient une table avec 410 lignes et 22 colonnes. Cette table sera utile pour les analyses statistiques.
tot<-Reduce(function(x, y) merge(x, y, by="Capteur"), list(trafic_2009,trafic_2010,trafic_2011,trafic_2012, trafic_2013,trafic_2014,trafic_2015))
tot[1:3,]
## Capteur HPM.2009 HPS.2009 MJO.2009 HPM.2010 HPS.2010 MJO.2010 HPM.2011
## 1 Z05AE 171 200 2284 155 189 2186 150,14
## 2 Z05AS 729 1070 12588 649 1046 11764 621,58
## 3 Z05BE 677 573 7909 629 539 7297 580,35
## HPS.2011 MJO.2011 HPM.2012 HPS.2012 MJO.2012 HPM.2013 HPS.2013 MJO.2013
## 1 178 2012,48 149 162 1913 139 172 1956
## 2 1050,79 11705,98 603 1036 11411 637 1007 11586
## 3 488,91 6935,86 550 490 6626 531 530 6821
## HPM.2014 HPS.2014 MJO.2014 HPM.2015 HPS.2015 MJO.2015
## 1 140 187 2301 122 126 1777
## 2 630 942 11174 634 995 11015
## 3 522 515 6836 535 512 6689
dim(tot)
## [1] 410 22
Tout d'abord, on a voulu faire une analyse spatiale des capteurs. On a pas un accès direct au coordonnées géographiques, mais, on trouve un fichier.csv avec les identifiants et leurs adresses.
geo<-read.csv("Anibarro-Rambier/adresses_OK.csv")
head(geo)
## X cartodb_id ident type
## 1 2 478 Z25CT11 BOUCLE
## 2 3 37 Z10CT18 BOUCLE
## 3 4 473 Z14CT24 BOUCLE
## 4 5 475 Z14CT23 BOUCLE
## 5 6 476 Z25CT14 BOUCLE
## 6 7 315 Z30CT7 BOUCLE
## adresse
## 1 Allée de Boutaut, 33520 Bruges, France
## 2 92-94 Rue de la Béchade, 33000 Bordeaux, France
## 3 87 Quai de Brazza, 33100 Bordeaux, France
## 4 54-75 Quai de Brazza, 33100 Bordeaux, France
## 5 Allée de Boutaut, 33520 Bruges, France
## 6 20 Avenue de Belfort, 33700 Mérignac, France
On décide alors, de géolocaliser les 482 capteurs, dont on connait l'adresse, en intérogeant l'API Google Maps.
library(RCurl)
library(RJSONIO)
library(plyr)
url <- function(address, return.call = "json", sensor = "false") {
root <- "http://maps.google.com/maps/api/geocode/"
u <- paste(root, return.call, "?address=", address, "&sensor=", sensor, sep = "")
return(URLencode(u))
}
geoCode <- function(address,verbose=FALSE) {
if(verbose) cat(address,"\n")
u <- url(address)
doc <- getURL(u)
x <- fromJSON(doc,simplify = FALSE)
if(x$status=="OK") {
lat <- x$results[[1]]$geometry$location$lat
lng <- x$results[[1]]$geometry$location$lng
location_type <- x$results[[1]]$geometry$location_type
formatted_address <- x$results[[1]]$formatted_address
return(c(lat, lng, location_type, formatted_address))
} else {
return(c(NA,NA,NA, NA))
}
}
Application à nos données:
longitude<-NULL
latitude<-NULL
for ( i in 1:482){
address <- geoCode(as.character(geo$adresse[[i]]))
longitude<-c(longitude,address[1])
latitude<-c(latitude,address[2])
print(longitude)
print(latitude)
}
longitude<-as.numeric(longitude)
latitude<-as.numeric(latitude)
tab<-cbind(as.character(geo$adresse), longitude, latitude)
Ce code met autour de 4 minutes à tourner donc on préfere charger directement le tableau "tab" obtenu.
coord<-read.csv("Anibarro-Rambier/coord_geo_OK.csv")
coord[1:3,]
## cartodb_id ident type
## 1 478 Z25CT11 BOUCLE
## 2 37 Z10CT18 BOUCLE
## 3 473 Z14CT24 BOUCLE
## adresse coordonnees_kml2
## 1 Allée de Boutaut, 33520 Bruges, France 44.87473
## 2 92-94 Rue de la Béchade, 33000 Bordeaux, France 44.82396
## 3 87 Quai de Brazza, 33100 Bordeaux, France 44.85776
## coordonnees_kml
## 1 -0.5767857
## 2 -0.5997033
## 3 -0.5465689
L'intérêt d'avoir les coordonnées est de pourvoir ainsi les placer sur un carte de la ville de Bordeaux et pouvoir visualiser les positions. Pour ceci, après plusieurs essais, on décide d'utiliser le package RgoogleMaps.
library(RgoogleMaps)
map.bdx <- GetMap(center=c(44.8404400,-0.5805000), zoom = 13, destfile = "bdx.png", maptype = "mobile")
lat<-as.numeric(coord$coordonnees_kml2)
long<-as.numeric(coord$coordonnees_kml)
bb <- qbbox(lat = as.numeric(lat),
lon = as.numeric(long))
bdx3 <- GetMap.bbox(latR = bb$latR,
lonR = bb$lonR,
destfile = "bdx3.png",
maptype="mobile", zoom=12
)
PlotOnStaticMap(bdx3,
lat = as.numeric(lat), lon = as.numeric(long),
cex = 0.5, pch = 19, col = "red", add = FALSE)
##ACP
Maintenant qu'on a notre tableau total et les positions géographiques on commence à faire des analyses statistiques.
On commence par une ACP sur le tableau des données complètes. Une fois qu'on a les nouvelles coordonnées, l'agorithme des k-means avec k=2 nous semble adapté ici pour différencier les capteurs.
En effet, on peut voir en rouge les capteurs placés sur les boulevards, les quais et les entrées et sorties de la Rocade, les endroits qui ont tendance à être embouteillés.
lat<-as.numeric(tot$coordonnees_kml2)
long<-as.numeric(tot$coordonnees_kml)
PlotOnStaticMap(bdx3,
lat = as.numeric(lat), lon = as.numeric(long),
cex = gros, pch = 19, col = couleur, add = FALSE)
# Influence de l'ouverture du Pont Chaban Delmas
Inauguré en Mars 2013, le pont Chaban Delmas a été construit pour fluidifier le trafic le long des quais, en proposant des chemins alternatifs aux conducteurs. On va voir comment ceci a eu un impact sur les capteurs.
On commence par étudier 9 capteurs qui sont sur les quais entre le pont Chaban Delmas et le Pont de Pierre.
On constate tout d'abord qu'en 2011 il y a eu des travaux, ou un autre
facteur (peut être un problème technique sur les capteurs de la CUB),
qui a négativement influencé les passages de voitures à cette heure là.
Hormis ceci, on peut conclure que l'ouverture du pont n'a pas significativement changé les chemins des voitures puisque les bordelais continuent d'emprûnter les quais de la rive gauche.
La même chose le soir entre 17h et 18h...le pont ne change rien.
On dispose que de deux capteurs sur la rive droite et on ne constate pas de grand changement.
Cette partie est légèrement décevante puisqu'on constate qu'un des
aménagements principaux de la ville ne semble avoir aucun impact sur le
trafic. On se demande si c'est une erreur de notre de notre part ou si
le pont ne sert à rien...
Pour cette dernière partie on décide de voir la carte des capteurs comme un graphe et de mettre en évidence les "liens" entre les capteurs qui se ressemblent.
Pour ceci, on reprend les coordonnées obtenues selon l'ACP. On veut maintenant regrouper les capteurs "semblables". On se limite aux 2 capteurs les plus proches et on construit la matrice A qui pour chaque capteur nous donne les 2 plus proches voisins en termes d'ACP.
head(A)
## CENTRE 1 PLUS PROCHE 2 PLUS PROCHE
## 1 Z05AE Z3CT3 Z14CT9
## 2 Z05AS Z30CT3 Z8CT6
## 3 Z05BE Z9CT12 Z18CT2
## 4 Z05BS Z6CT6 Z21BE
## 5 Z06AE Z30AS Z17CT5
## 6 Z06AS Z16AE Z6CT9
Modification de matrice A en termes de liens FROM-->TO:
head(liens)
## from to
## [1,] "Z05AE" "Z3CT3"
## [2,] "Z05AE" "Z14CT9"
## [3,] "Z05AS" "Z30CT3"
## [4,] "Z05AS" "Z8CT6"
## [5,] "Z05BE" "Z9CT12"
## [6,] "Z05BE" "Z18CT2"
Maintenant qu'on a la matrice des liens on va utiliser la package igraph pour contruire et visualiser le graphe.
##
## Attaching package: 'igraph'
## The following objects are masked from 'package:stats':
##
## decompose, spectrum
## The following object is masked from 'package:base':
##
## union
On se limite aux 50 premiers capteurs pour obtenir un graphe lisible et clair.
plot.igraph(net,vertex.label.color="black",vertex.shape="none", vertex.label.dist=0, vertex.size=10, edge.arrow.mode=0, edge.color="red", edge.width=2,
vertex.label.cex=0.7, layout=l, main="Liens entre les capteurs selon ACP")
On va étudier ceci grâce à un exemple. On décide d'analyse le chemin
entre le capteur Z16CT14 et Z24CT3. Comme on peut voir en haut à gauche
sur la graphique ci-dessus, le chemin le plus "rapide" selon l'ACP
serait de faire:
Z16CT14->Z10CT15->Z10AS->Z10CT14->Z24CT3
En contraste, on trace les coordonnées géographiques de ces points intermédiaires.
Le graphique montre que pour aller du Départ à la Fin, si on suit le
chemin de l'ACP, on fait un très grand détour par les Boulevards!
Ceci est bien en accord avec notre intuition puisque l'ACP conseille des chemins par capteurs "semblables" mais ceci ne veut pas forcément dire proches. En définitive, on peut avoir des capteurs très embouteillés relativement proches de capteurs où la circulation est fluide.