Les objectifs définis à la dernière séance étaient :
Cette séance nous avons décidé de travailler sur :
La projection des différents points sur un fond de carte GoogleMaps est réalisé grâce à la librarie gmplot, qui peut être trouvé sur le repository GitHub <a href= https://github.com/vgm64/gmplot > suivant</a>.
import gmplot
Le fond de carte à proprement parlé est généré par la fonction gmplot.GoogleMapPlotter .
Celle ci prend 3 entrées :
La dernière entrée est une clé API que nous avons dû enregistrer auprès de Google afin de pouvoir utiliser l'API Google Maps.
gmap = gmplot.GoogleMapPlotter( 45.757589, 4.831689, 13, apikey="AIzaSyDsYwvF3UUxTx8RB40wd4SnUVzfnbW66LM")
Les données qui nous intéressent peuvent être affichées en utilisant les fonctions :
gmap.plot([45.784062,45.757071,45.760616], [4.767291,4.833720, 4.858056], 'cornflowerblue', edge_width=10)
gmap.scatter([45.784062,45.757071,45.760616],[4.767291,4.833720, 4.858056], '#3B0B39', size=40, marker=False)
gmap.scatter([45.784062,45.757071,45.760616], [4.767291,4.833720, 4.858056], 'k', marker=True)
gmap.heatmap([45.784062,45.757071,45.760616], [4.767291,4.833720, 4.858056])
gmap.draw("figure/2-LyonMap.html")
Enfin l'aperçu de la page web sauvegardée est visible grâce à la fonction IFrame .
import gmplot
gmap = gmplot.GoogleMapPlotter( 45.757589, 4.831689 , 13,apikey=" AIzaSyDsYwvF3UUxTx8RB40wd4SnUVzfnbW66LM ")
gmap.plot([45.784062,45.757071,45.760616], [4.767291,4.833720, 4.858056], 'cornflowerblue', edge_width=10)
gmap.scatter([45.784062,45.757071,45.760616],[4.767291,4.833720, 4.858056], '#3B0B39', size=40, marker=False)
gmap.scatter([45.784062,45.757071,45.760616], [4.767291,4.833720, 4.858056], 'k', marker=True)
gmap.heatmap([45.784062,45.757071,45.760616], [4.767291,4.833720, 4.858056])
gmap.draw("figure/2-lyonmap.html")
from IPython.display import IFrame
IFrame('figure/2-lyonmap.html', width=990, height=500)
Dans un premier temps nous créons un data frame à partir du fichier Json. Nous ne gardons que les colonnes intéressantes, c'est à dire :
Nous avons d'autre part ajouté
Notons bien que les latitudes et longitudes ont, au cours de ces opérations, été mises au format standart, et non plus E7.
Par la suite, nous rajoutons certaines colonnes, que nous calculons à partir de données citées précédamment. Il s'agit dans un premier temps de la distance qui sépare un point du prochain point.
Nous rajoutons également la vitesse à laquelle l'utilisateur se trouve en un point. Il est important de noter que nous calculons la vitesse moyenne entre deux points, et que nous associons la vitesse moyenne à la vitesse du premier point.
Ces hypothèses font du sens pour le moment, elles pourront être modifiées par la suite si besoin.
La vitesse est exprimée en km/h.
L'ensemble de ces fonction est rassemblé dans la fonction parser.getData(nameFile,bComputeDistance,bComputeVitesse) .
import parser
import distance
df = parser.importJson("data/anonymous_2015.json")
max(df['velocity'])
Nous avons ensuite décidé de tracer la vitesse en fonction du temps pour avoir une idée des résultats obtenus. On voit donc bien qu'il y a un certains nombre de points aberrants. La vitesse maximale est de 2182 km/h ce qui paraît très peu réaliste !
import matplotlib.pyplot as plt
plt.figure(figsize=(12,8))
plt.plot(df["velocity"],'-')
plt.grid(True)
plt.xlabel('Echantillons')
plt.ylabel('Vitesse (km/h)')
plt.show()
Pour mieux se rendre compte de ce qu'il se passe, nous avons décidé de nous concentrer uniquement sur la journée du 21 septembre 2015. On sait que ce jour là, l'utilisateur se trouvait à lyon.
Nous avons crée une fonction permettant de sélectionner directement les données du jour qui nous intéresse.
data = parser.selectDate("21-09-2015", df)
data.head()
Nous avons traçé cette journée, de la même manière qui a été vue plus haut.
lat = data['latitude']
lng = data['longitude']
import gmplot
gmap = gmplot.GoogleMapPlotter(45.757589, 4.831689, 13, apikey="AIzaSyDsYwvF3UUxTx8RB40wd4SnUVzfnbW66LM")
gmap.plot(lat, lng, 'cornflowerblue', edge_width=3)
gmap.draw("figure/2-lyon-map-data-an.html")
from IPython.display import IFrame
IFrame('figure/2-lyon-map-data-an.html', width=990, height=500)
Nous avons ensuite traçé les vitesses relatives à cette journée.
Nous pouvons constater que les vitesse calculée sembllent cohérentent.
import matplotlib.pyplot as plt
plt.figure(figsize=(12,8))
plt.plot(data["velocity"],'-')
plt.grid(True)
plt.ylabel('Vitesse (km/h)')
plt.xlabel('Echantillons au cours de la journée')
plt.show()
On commence par implémenter les filtres mean filter et median filter.
Ces filtres remplacent les coordonnées des points (longitude et latitude) par respectivement leurs valeurs moyenne et mediane calculées sur une fenêtre de points centrée sur le point en question. Par exemple pour une fenêtre de taille 5, les longitude et latitude du point sont remplacées par la moyenne ou médiane des longitudes et latitudes de l'ensemble composé du point en question, des deux points précédents et des deux points suivants.
Ces filtres fonctionnent bien sur des points proches (spatialement et temporellement) mais sont moins pertinent sur des points très éloignés, en particulier lorsque beaucoup de temps les sépare. Une condition importante pour bien pouvoir les utiliser sera donc de bien segmenter les trajets en périodes temporelles cohérentes, pour pouvoir utiliser ces filtres sur des points constitutifs d'un même trajet. Cette segmentation sera explorée ultérieurement.
De plus vient la question de l'utilisation de ces filtres. En effet deux usages peuvent en être fait:
On applique le filtre simplement (premier usage) aux déplacements non segmentés de la journée du 21 septembre 2015.
n=2 ## la fenêtre glissante sera de taille 2n+1
lat_filtered=[0]*len(data) ## initialisation des tableaux
long_filtered=[0]*len(data)
for i in range(n):
lat_filtered[i]=data['latitude'][i]
long_filtered[i]=data['longitude'][i]
for i in range(len(data)-n,len(data)):
lat_filtered[i]=data['latitude'][i]
long_filtered[i]=data['longitude'][i]
for i in range(n, len(data)-n):
for j in range(i-n,i+n+1):
lat_filtered[i]+=data['latitude'][j]/(2*n+1)
long_filtered[i]+=data['longitude'][j]/(2*n+1)
lat_original = data['latitude'].values
long_original = data['longitude'].values
plt.figure(figsize=(12,8))
plt.grid(True)
plt.xlabel('Latitude')
plt.ylabel('Longitude')
plt.plot(lat_original, long_original,label="Parcours brute")
plt.plot(lat_filtered, long_filtered, 'r',label="Parcours filtré")
plt.legend(loc='upper left')
plt.savefig('figure/2-mean-filter.png')
plt.show()
On remarque que les chemins filtrés (en rouge) sont pertinents pour des séquences de déplacement (les deux trajets en diagonal) mais beaucoup moins pour les déambulation autour d'un point. Cela confirme la nécesité de n'appliquer ces filtres qu'à des segments de trajets.
n = 2
for i in range(n, len(data)-n):
lat_window = data['latitude'][i-n:i+n+1].tolist()
lat_window.sort()
long_window = data['longitude'][i-n:i+n+1].tolist()
long_window.sort()
lat_filtered[i] = lat_window[n]
long_filtered[i] = long_window[n]
plt.figure(figsize=(12,8))
plt.grid(True)
plt.xlabel('Latitude')
plt.ylabel('Longitude')
plt.plot(lat_original, long_original,label="Parcours brute")
plt.plot(lat_filtered, long_filtered, 'r',label="Parcours filtré")
plt.legend(loc='upper left')
plt.savefig('figure/2-median-filter.png')
plt.show()
On remarque que le median filter est plus fidèle aux données brutes lorsque le trajet est pertinent mais s'éloigne d'autant plus des points aberrants (notamment le point en haut à gauche). De même pour des trajets de déambulation
Pour la partie chargement des données nous pouvons faire les conclusions suivantes :
L'affichage de la carte est terminé.
Le chargement des données est terminé.
Les pistes de travail pour la semaine prochaine sont :