import pandas as pd
import numpy as np
import datetime as dt
Un peu de cartographie¶
On va regarder comment dessiner une carte géographique avec de l'information par dessus.
Note : si les cartes ne sont pas visibles à l'ouverture de la feuille, veuillez recalculer toutes les cellules avec Cell -> Run all
.
Les données : le prix de l'essence¶
On récupère les prix du jour de l'essence dans les stations de France sur https://www.prix-carburants.gouv.fr/ (voir le programme prix_carburants.py qui fait le travail).
from data import prix_carburants
df = prix_carburants.get_gaz_price()
print("Nombre de données : ", len(df))
df.head()
Nombre de données : 33496
adresse | cp | ville | latitude | longitude | essence | prix | maj | |
---|---|---|---|---|---|---|---|---|
0 | 596 AVENUE DE TREVOUX | 01000 | SAINT-DENIS-LèS-BOURG | 46.201 | 5.198 | Gazole | 1.799 | 2024-02-22 00:46:00 |
1 | 596 AVENUE DE TREVOUX | 01000 | SAINT-DENIS-LèS-BOURG | 46.201 | 5.198 | SP95 | 1.884 | 2024-02-22 00:46:00 |
2 | 596 AVENUE DE TREVOUX | 01000 | SAINT-DENIS-LèS-BOURG | 46.201 | 5.198 | E85 | 0.849 | 2024-02-22 00:46:00 |
3 | 596 AVENUE DE TREVOUX | 01000 | SAINT-DENIS-LèS-BOURG | 46.201 | 5.198 | E10 | 1.848 | 2024-02-22 00:46:00 |
4 | 596 AVENUE DE TREVOUX | 01000 | SAINT-DENIS-LèS-BOURG | 46.201 | 5.198 | SP98 | 1.952 | 2024-02-22 00:46:00 |
Certaines données ne semble pas avoir été mises à jour, aussi je filtre :
df =df[df.maj > np.datetime64('today') - np.timedelta64(30)] # keep 30 last days of price updated
len(df)
31643
Récupérons les 10 meilleurs prix et les 10 pires pour l'essence sans plomb 95 européenne (E10). Attention certaines stations ne mettent pas à jour leur prix ce qui fait qu'on peut avoir des prix d'il y a un an, donc totalement faux !
e10 = df[df.essence.isin(['E10', 'SP95'])].sort_values('prix')
print('Nombre de stations prises en compte : %d' % len(e10))
worst = e10[-10:]
best = e10[:10]
best
Nombre de stations prises en compte : 10597
adresse | cp | ville | latitude | longitude | essence | prix | maj | |
---|---|---|---|---|---|---|---|---|
9189 | ROUTE DE ST GILLES | 30132 | CAISSARGUES | 43.784000 | 4.393000 | SP95 | 1.193 | 2024-02-04 19:26:16 |
5035 | 1 RUE D'ALIGRE | 17230 | MARANS | 46.311311 | -0.991826 | E10 | 1.715 | 2024-02-23 09:00:00 |
8819 | 137 Avenue Maréchal Foch | 29400 | Landivisiau | 48.514888 | -4.053751 | E10 | 1.725 | 2024-02-24 05:57:00 |
8823 | Boulevard de la République | 29400 | LANDIVISIAU | 48.503959 | -4.073226 | E10 | 1.726 | 2024-02-23 08:27:15 |
15171 | 24 , ROUTE DE COUERON | 44360 | SAINT-ÉTIENNE-DE-MONTLUC | 47.270000 | -1.776000 | E10 | 1.734 | 2024-02-23 08:29:41 |
15178 | LIEU DIT TOURNEBRIDE | 44360 | Saint-Étienne-de-Montluc | 47.278000 | -1.721000 | E10 | 1.734 | 2024-02-23 07:45:20 |
30689 | rd pt de l'Europe parc Océanis | 85800 | Saint-Gilles-Croix-de-Vie | 46.694000 | -1.914000 | E10 | 1.735 | 2024-02-25 01:17:00 |
30540 | 87 Avenue François Mitterand | 85340 | Olonne-sur-Mer | 46.513501 | -1.777663 | E10 | 1.735 | 2024-02-25 01:17:00 |
30487 | Avenue du Terre Fort Face Hyper U | 85270 | SAINT-HILAIRE-DE-RIEZ | 46.713000 | -1.961000 | E10 | 1.735 | 2024-02-24 09:34:11 |
30533 | 73 Rue du 8 Mai 1945 | 85340 | Olonne Sur Mer | 46.543000 | -1.772000 | E10 | 1.735 | 2024-02-24 09:54:30 |
Parfois il y a des prix d'essence incroyablement bas, genre erreur. On pourrait filtrer par valeur aussi.
Folium¶
Folium est une des bibliothèques bien adaptée pour faire de la cartographie. Elle s'appuie sur la bibliothèque Javascript Leaflet laquelle utilise les cartes de
- OpenStreetMap par défaut (libre)
- Staten s'appuie sur OpenStreetMao mais produit un rendu différent
- Boxmap (compte gratuit limité possible)
Il est possible d'utiliser les cartes de Google si on a un compte qui le permet avec FoliumGEE.
Fond de carte¶
Les principaux fonds de carte sont OpenStreetMap
(par défaut), Stamen Terrain
, Staten Toner
, Statemen Watercolor
, Mapbox Bright
et Mapbox Control
.
import folium
Marqueurs¶
On commence par placer des marqueurs avec folium.Marker
et un joli cercle vert :
france = folium.Map(location=[46.8,2], zoom_start=6)
for lat,lon,val in zip(best.latitude, best.longitude, best.prix):
folium.Marker((lat,lon), popup="%.2f €/l" % val).add_to(france) # default marker
for lat,lon,val in zip(worst.latitude, worst.longitude, worst.prix):
folium.Marker((lat,lon),
icon=folium.Icon(color='red', icon='exclamation-sign'), # custumized marker
popup="%.2f €/l" % val
).add_to(france)
vb = best.iloc[0] # very best
folium.CircleMarker((vb.latitude,vb.longitude), radius=20,
popup='Best !', color='green').add_to(france)
france
Bien sûr on peut zoomer et déplacer la carte. On note que certaines coordonnées latitude/longitude sont approximatives...
Icônes¶
Pour les icônes possibles voir https://github.com/lvoogdt/Leaflet.awesome-markers
Objets géographiques¶
GeoJSON est un format ouvert pour définir des objets géographique. Folium permet d'afficher directement ces objets folium.GeoJson
et folium.TopoJson
(comme on a utilisé folium.Marker
).
Mais on peut aussi colorier les objets ajoutés en fonction de données dans un tableau. Ainsi sur France Geojson on peut récupérer les entités administratives de la France ce qui va nous permettre de faire une carte coloriée avec le prix moyen de l'essence par département.
Pour cela il faut un DataFrame qui ait une valeur par département et donc aussi l'identifiant du département. Dans le fichier récupéré sur France Geojson, on note que le code des départements est une chaîne de 2 caractères. Il faut donc avoir la même chaine dans notre tableau.
df['département'] = df.cp.apply(lambda x:x[:2])
prix_dep = df[(df.essence == 'E10') & (df.maj + dt.timedelta(days=30) > dt.datetime.now())] \
[['département','prix']].groupby('département', as_index=False).mean()
display(prix_dep.sort_values('prix').head(2))
display(prix_dep.sort_values('prix').tail(2))
département | prix | |
---|---|---|
27 | 29 | 1.787747 |
83 | 85 | 1.794893 |
département | prix | |
---|---|---|
90 | 92 | 1.934878 |
73 | 75 | 1.979611 |
france = folium.Map(location=[46.5,2], zoom_start=5)
colors = folium.Choropleth(geo_data = 'data/departements-version-simplifiee.geojson',
data = prix_dep,
columns = ['département', 'prix'],
key_on = 'feature.properties.code',
fill_color = 'YlOrRd',
fill_opacity = 0.6,
line_opacity = 0.2,
legend_name = "Prix de l\\'essence E10"
)
colors.add_to(france)
folium.LayerControl().add_to(france)
france
La Corse pose un problème de notation (20 pour l'essence, 2A et 2B pour la carte).
Folium propose un résumé rapide qui reprend tout ces points.
Plotly¶
Plotly propose aussi d'afficher des cartes. Elle s'appuie sur Mapbox.
import plotly.express as px
import json
departements = json.load(open('data/departements-version-simplifiee.geojson'))
fig = px.choropleth_mapbox(prix_dep, geojson=departements,
locations='département', featureidkey = 'properties.code', # join keys
color='prix', color_continuous_scale="Viridis",
mapbox_style="carto-positron",
zoom=4.6, center = {"lat": 47, "lon": 2},
opacity=0.5,
labels={'prix':'Prix E10'}
)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig