JCDecaux à ouvert son site web open data où l’on peux trouver toutes les informations relatives à leur solutions de vélo publique implémentées dans différentes villes comme Paris, Lyon, Marseille pour la France et Bruxelle, Toyama ou encore Goetborg pour le reste du monde.
C’est une très bonne nouvelle, car on a enfin une solution officielle nous fournissant des données assez utiles sur les stations de vélo dans les villes ainsi que l’état en temps réels de ces dernières.
J’ai voulu jouer avec ces données.
J’ai pris le json de la carte de Paris, qui donne toutes les stations de Vélib comme ceci:
[ {"number":7022, // un identifiant "name":"07022 - PONT DE L'ALMA", // Un nom "address":"3 AVENUE BOSQUET - 75007 PARIS", // l'adresse de la station "latitude":48.86164049957625, // sa latitude "longitude":2.302250344175951}, // sa longitude {..} ,.. ]
Et tout ça, ça s’exporte bien dans Gephi !
import json from GephiStreamer import Node,Edge,GephiStreamerManager t = GephiStreamerManager() with open('Paris.json', 'r') as f: read_data = f.read() f.closed jdata = json.loads(read_data) for d in jdata: print d['number'] n= Node(d['number'],label=d['name']) n.property['address'] = d['address'] n.property['latitude'] = d['latitude'] n.property['longitude'] = d['longitude'] t.add_node(n) t.commit()
Un coup de Geo-Layout et pof, on a une belle représentation de nos stations.
Mais, ça manque un peu de lien, alors on va en créer.
1er idée
Relier une station A à une autre station B si B est la station la plus proche de A.
t = GephiStreamerManager() with open('Paris.json', 'r') as f: read_data = f.read() f.closed jdata = json.loads(read_data) for d in jdata: print d['number'] n= Node(d['number'],label=d['name']) n.property['address'] = d['address'] n.property['latitude'] = d['latitude'] n.property['longitude'] = d['longitude'] t.add_node(n) t.commit() map_distance = {} for d in jdata: map_distance[d['number']]=[] for dd in jdata: if dd['number'] != d['number']: latpow = (d['latitude']-dd['latitude'])*(d['latitude']-dd['latitude']) lonpow = (d['longitude']-dd['longitude'])*(d['longitude']-dd['longitude']) dist = math.sqrt(latpow+lonpow) map_distance[d['number']]+=[{'id':dd['number'],'dist':dist}] for d in map_distance: for m in map_distance[d]: m = min(map_distance[d], key=lambda x:x['dist']) e = Edge(d,m['id'],False) t.add_edge(e) t.commit()
Et tada ! Un bel ensemble d’îlots de stations !
2e idée
Relier une station A à une station B si A et B sont distantes de moins d’ 1 kilomètres
/!\ Pour calculer la distance entre 2 points, on utilise généralement la distance euclidienne. Ici on utilise des points génographique avec des coordonnées en degrés. Vu que la distance exprimé ne représente pas quelques chose de très commun ( une distance en degrés si je me trompe pas) et qu’on travaille sur une petite surface (on va omettre les problématiques d’Orthodromie ) je prends comme base que 0.01 Degré = 832.2m ou 1000m = 0.0120163422254266 Degré
t = GephiStreamerManager() with open('Paris.json', 'r') as f: read_data = f.read() f.closed jdata = json.loads(read_data) for d in jdata: print d['number'] n= Node(d['number'],label=d['name']) n.property['address'] = d['address'] n.property['latitude'] = d['latitude'] n.property['longitude'] = d['longitude'] t.add_node(n) t.commit() #0.01 = 0.8322km = 832.2m map_distance = {} moydis = 0 countdis = 0 for d in jdata: map_distance[d['number']]=[] for dd in jdata: if dd['number'] != d['number']: latpow = (d['latitude']-dd['latitude'])*(d['latitude']-dd['latitude']) lonpow = (d['longitude']-dd['longitude'])*(d['longitude']-dd['longitude']) dist = math.sqrt(latpow+lonpow) map_distance[d['number']]+=[{'id':dd['number'],'dist':dist}] for d in map_distance: for m in map_distance[d]: moydis += m['dist'] countdis +=1 if m['dist'] <= 0.0120163422254266: e = Edge(d,m['id'],False,weight=(m['dist']/0.0120163422254266)*1000) e.property['dist'] = (m['dist']/0.0120163422254266)*1000 t.add_edge(e) print "Distance moyenne : %s"%(moydis/countdis) t.commit()
et Tada !
On voit bien que le cœur des stations vélib se trouvent dans le centre de paris (pas le centre centre, il est légèrement décalé vers le nord). Néanmoins, on voit que la disposition des stations n’est pas homogène dans son ensemble, on trouve des « communautés » de stations, voir des micro-îlots (2 à 3 stations) qui sont exclus de la composante principale.
Une autre visualisation en cours de création est une réalisation que j’avais essayé de faire il y’a quelques années, et qui n’avait pas aboutit, faute d’accès trop fréquent à l’API (officieuse à l’époque :D). Il s’agit de voir l’évolution de l’occupation des stations au cours du temps via time-laps, grâce à la nouvelle Api temps réel de JCDecaux qui nous facilite grandement l’accès aux données.