Index
Compétition Kaggle : « New York City Taxi Fare Prediction »
Récemment en me lançant dans la compétition Kaggle sur la prédiction du montant des courses des taxis New Yorkais je me suis confronté au traitement de données de localisation. Pour précisément j’ai du traiter des données Géo-Localisées (Latitude-Longitude). Pour tout dire dans cette compétition Kaggle on n’a presque que ça comme données ! en gros on récupère les coordonnées de récupération du(des) client(s) et celles de l’endroit où le taxi les a déposé(s), et c’est presque tout !

Comme je le disais on a très peu de données, il va donc falloir exploiter au maximum ces informations pour par exemple :
- Déterminer la distance entre les points de récupération-dépose
- Déterminer le temps de trajet (car bien sur celui-ci a un impact sur le montant de la course)
- Supprimer les outliers. En regardant de près sur une carte on constatera certainement que des points sont hors limites, voire même dans l’eau ! il faudra supprimer ces données inexploitables.
- Détecter la proximité d’un aéorport … en effet les courses vers ce type de destination sont bien souvent forfaitaires.
- etc.
Pour cela il faut pouvoir exploiter les données de géolocalisation.
Vérifier que les données sont dans un cadre
Dans l’exemple des taxis c’est plutôt simple car nous devons restreindre les données géolocalisées au secteur de New York. Les autres données seront considérées comme des outliers (erreurs ou exceptions) que nous retirerons simplement du jeu de données. Ces données n’étant pas signifiante pour notre modèle.
Pour cela récupérons simplement les coordonnées de New-York sur internet …
On récupère donc les informations suivantes :
Les coordonnées de New York en degrés décimaux:
Latitude : 40.7142700°
Longitude : -74.0059700°Les coordonnées de New York en degrés et minutes décimales:
Latitude : 40°42.8562′ Nord
Longitude : 74°0.3582′ Ouest
On va maintenant définir un cadre d’appartenance à New York (forcément on sera approximatif ici, la vile de NYC n’étant pas située dans un cadre parfait): (-74.3, -73.7, 40.5, 40.9)
Ensuite on définit une simple fonction (Python) AppartientCadre() qui vérifie que des coordonnées en entrée figurent bien dans le cadre voulu:
<pre class="wp-block-syntaxhighlighter-code">nycBox = (-74.3, -73.7, 40.5, 40.9)
# Cette fonction vérifie que les coordonnées passées (df) sont bien dans le cadre BB
def AppartientCadre(df, _nycBox):
return (df.pickup_longitude <= _nycBox[0]) & \
(df.pickup_longitude <= _nycBox[1]) & \
(df.pickup_latitude <= _nycBox[2]) & \
(df.pickup_latitude <= _nycBox[3]) & \
(df.dropoff_longitude <= _nycBox[0]) & \
(df.dropoff_longitude <= _nycBox[1]) & \
(df.dropoff_latitude <= _nycBox[2]) & \
(df.dropoff_latitude <= _nycBox[3])
pd_sample = pd_sample[AppartientCadre(pd_sample, nycBox)]</pre>
Affichage sur une carte
Voilà on a supprimé quelques outliers, mais il serait interressant de voir un peu à quoi ressemblent nos données vous ne trouvez pas ? pour cela je vous propose de les visualiser sur une carte. Pour cela on a encore la possibilité d’utiliser Google Maps en créant une carte avec les points que nous avons. Certains sites proposent même ce service via import d’un fichier par exemple. Néanmoins nous n’allons pas procéder comme cela car nous avons vraiment beaucoup de point à visualiser.
Nous allons superposer nos points sur une image (carte). Notre seul prérequis est de posséder une carte (image) et surtout de connaitre ses coordonnées GPS.
Pour notre exemple nous récupérons la carte via https://aiblog.nl/download/nyc_-74.3_-73.7_40.5_40.9.png
Ses coordonnées sont (–74.3, –73.7, 40.5, 40.9) … non ce n’est pas un hasard, il s’agit bien du cadre de validation des coordonnées précédent 😉
Nous allons maintenant tracer sur cette image nos points avec la librairie matplotlib (scatterplot) :
import matplotlib.pyplot as plt
nyc = plt.imread('https://aiblog.nl/download/nyc_-74.3_-73.7_40.5_40.9.png')
def plotOnImage(df, _nycBox, nyc_map):
fig, a = plt.subplots(ncols=1, figsize=(10, 10))
a.set_title("Points sur NYC")
a.set_xlim((_nycBox[0], _nycBox[1]))
a.set_ylim((_nycBox[2], _nycBox[3]))
a.scatter(df.pickup_longitude, df.pickup_latitude, zorder=1, alpha=0.3, c='r', s=1)
a.imshow(nyc, zorder=0, extent=_nycBox)
plotOnImage(pd_sample, BB, nyc_map)
Regardez le résultat :

Les points sont tracés en rouge. On observe la concentration de ces dernier dans le centre ville comme on aurait pu s’y attendre !
Calculer la distance
La distance est bien sur une donnée importante à récupérer. Pour cela on peut avoir encore plusieurs approches. On peut calculer la distance entre deux point via la formule de Haversine ou alors utiliser les API Google Maps. Nous allons voir ces deux approches.
Calcul via la formule de Haversine
Voilà la formule mathématique :

Alors évidemment cette formule peut paraitre bien complexe. Mais ça serait oublier que nous sommes sur terre et que cette bonne vieille terre est sphérique ! il est donc impensable (sauf pour de très courtes distances) de ne pas prendre en considération la forme sphérique de la terre. D’où cette formule donc …
En Python, voilà ce que ça donne :
def distance(lat1, lon1, lat2, lon2):
p = 0.017453292519943295 # Pi/180
a = 0.5 - np.cos((lat2 - lat1) * p)/2 + np.cos(lat1 * p) * np.cos(lat2 * p) * (1 - np.cos((lon2 - lon1) * p)) / 2
return 0.6213712 * 12742 * np.arcsin(np.sqrt(a))
distance(pd_sample.pickup_latitude[0],
pd_sample.pickup_longitude[0],
pd_sample.dropoff_latitude[0],
pd_sample.dropoff_longitude[0])
Calcul via Google maps
Là ça se corse un peu car pour utiliser l’API Google vous devez :
- Avoir un compte Google (gmail)
- Déclarer l’utilisation de l’API afin d’obtenir une clé. Pour cela allez sur l’URL https://console.developers.google.com et ajoutez l’API Maps Distance
- importer la librairie googlemaps (https://github.com/googlemaps/google-maps-services-python) via
pip install googlemaps
Pour tester je vous invite à vérifier que l’API est bien active en tapant dans votre browser directement :
https://maps.googleapis.com/maps/api/distancematrix/json?units=imperial&origins=Washington,DC&destinations=New+York+City,NY&key=[VOTRE CLE ICI]
NB: remplacez [VOTRE CLE ICI] par la clé que vous avez récupéré sur le site Google.
Vous devez avoir cet écran :
Maintenant vous pouvez faire une appel via Python de l’API:
pd_sample['pickup'] = pd_train.pickup_latitude[0].astype(str)+","+pd_train.pickup_longitude[0].astype(str)
pd_sample['dropoff'] = pd_train.dropoff_latitude[0].astype(str)+","+pd_train.dropoff_longitude[0].astype(str)
print ("Pickup:" + pd_sample['pickup'][0])
print ("Dropoff:" + pd_sample['dropoff'][0])
import googlemaps
gmaps = googlemaps.Client(key="[VOTRE CLE ICI]")
def distance_googlemaps(pickup, dropoff):
geocode_result = gmaps.distance_matrix(pickup, dropoff)
try:
distance = float(geocode_result['rows'][0]['elements'][0]['distance']['text'].split()[0])
duration = geocode_result['rows'][0]['elements'][0]['duration']['text'].split()
if len(duration)==4:
mins = float(duration[0])*60 + float(duration[2])
else:
mins = float(duration[0])
except:
mins = np.nan
distance = np.nan
return pd.Series((distance, mins))
distance_googlemaps(pd_sample['pickup'][0], pd_sample['dropoff'][0])
Vous avez remarqué Google nous offre même la durée de trajet entre les deux points 🙂
Voila nous avons vu comment récupérer, visualiser et enrichir des données de géolocalisation. Nous avons efleuré l’API Google mais si vous regardez de plus près vous trouverez pleins d’autres fonctions utiles ainsi que des paramètres intéressant à ajuster.
J’ai, en plus de 15 ans, accumulé une solide expérience autour de projets variés d’intégration (données & applicatives). J’ai en effet travaillé au sein de neuf entreprises différentes et y ai successivement adopté la vision du fournisseur de service, du client final et de l’éditeur de logiciels. Cette expérience m’a naturellement conduit à intervenir dans des projets d’envergure autour de la digitalisation de processus métiers et ce principalement dans des secteurs d’activités tels que l’assurance et la finance.
Passionné d’IA (Machine Learning, NLP et Deep Learning), j’ai rejoint BluePrism en 2019 en tant que consultant solution avant-vente, où je combine mes compétences en la matière avec l’automatisation afin d’aider mes clients à robotiser de manière plus performante des processus métiers parfois complexes. En parallèle de mon activité professionnelle, j’anime ce blog dans le but de montrer comment comprendre et analyser des données le plus simplement possible.
Apprendre, convaincre par l’argumentation et transmettre mon savoir pourrait être mon triptyque caractéristique.
Bonjour,
j’ai une erreur quand j’execute la fonction AppartientCadre sur le daraframe pd_sample. il me dit :
name ‘pd_sample’ is not defined.
Voici mon code:
nycBox = (-74.3, -73.7, 40.5, 40.9)
def AppartientCadre(df, _nycBox):
return (df.pickup_longitude <= _nycBox[0]) & \
(df.pickup_longitude <= _nycBox[1]) & \
(df.pickup_latitude <= _nycBox[2]) & \
(df.pickup_latitude <= _nycBox[3])& \
(df.dropoff_longitude <= _nycBox[0]) & \
(df.dropoff_longitude <= _nycBox[1])& \
(df.dropoff_latitude <= _nycBox[2]) & \
(df.dropoff_latitude <= _nycBox[3])
pd_sample = pd_sample[AppartientCadre(pd_sample, nycBox)]
Merci de votre aide
Bonjour,
Pour vous aider j’ai mis dans GitHub le notebook Jupyter avec toutes les sources de cet article (https://github.com/datacorner/les-tutos-datacorner.fr/blob/master/etudes-de-cas/nyctaxifare/nyctaxifare.ipynb)
J’espère que ça voua aidera 😉
A bientôt
Benoît.