Interactive map with Bokeh
Visualize my 4 years of missions in consulting
Details of missions carried out at Horwath HTL (in French)
Tutorial (in French)
import pandas as pd
import numpy as np
from bokeh.plotting import figure
from bokeh.tile_providers import get_provider, Vendors
from bokeh.transform import factor_cmap
from bokeh.models.tools import WheelZoomTool
from bokeh.models import ColumnDataSource
from bokeh.io import show
Introductrion
Bokeh est une librairie de visualisation interactive pour python très puissante. La majorité des types de visualisation de données auquel ont peu penser peut se faire avec Bokeh. Ce tutorial explique comme réaliser une carte interactive avec affichage d’information au passage de la souris.
Les données
Pour réaliser la carte, on utilise un dataframe issu d’un fichier csv. Il contient les coordonnées GPS des points que l’on souhaite afficher d’autres attributs (du texte ici).
df_mission = pd.read_csv("missionsHTL.csv", sep=';', decimal=',')
df_mission.drop(columns=['type_business','année','loc_codegeo','loc_cp','pays'], inplace = True)
df.head()
type_etude | nom | client | latitude | longitude | |
---|---|---|---|---|---|
0 | Etude stratégique | Etude sur les opportunités di'nvestissement to... | BATIPART | 47.102391 | 11.290570 |
1 | Etude stratégique | Assistance pour le projet de mise en concessio... | BOAD | 6.135669 | 6.135669 |
2 | Audit de Société et potentiel de développement | Expertise de la société API&YOU | BPI France | 46.837821 | 5.709352 |
3 | Audit de Société et potentiel de développement | Expertise de la société LoungeUp | BPI France | 48.880410 | 2.350979 |
4 | Audit de Société et potentiel de développement | Analyse du marché des solutions de conciergeri... | BPI France | 48.879212 | 2.352816 |
La carte
Choisir le CRS (coordinate reference system)
Le système de coordonnées des données est le WGS 84. Il s’agit du référentiel standard que l’on retrouve sur service de cartographie en ligne.
Les fonds de cartes utilisés par Bokeh utilisent la projection Mercator. Il faut donc modifier le csr avant de faire la carte. On utilise la projection suivante:
k = 6378137
df_mission["x"] = df_mission['longitude'] * (k * np.pi / 180.0)
df_mission["y"] = np.log(np.tan((90 + df_mission['latitude']) * np.pi / 360.0)) * k
Chargement du fond de carte : Bokeh propose plusieurs types de fond de cartes, disponibles ici
tile_provider = get_provider(Vendors.CARTODBPOSITRON)
L’affichage intéractif est activé pour les colonnes ‘Client’ et ‘Missions’
TOOLTIPS = [
('Client', '@client'),
('Mission', '@name')]
Bokeh permet d’utiliser de nombreux outils pour les figures, par défaut la plupart sont présents, pour notre carte on choisit d’utiliser les suivants uniquement:
tools = "pan,wheel_zoom,box_zoom,reset"
Création de la figure
p = figure(x_range=(-2000000, 6000000), y_range=(-1000000, 7000000),
x_axis_type="mercator", y_axis_type="mercator",
tooltips=TOOLTIPS,
tools=tools,
plot_width=800,
plot_height=600
)
p.add_tile(tile_provider)
Afficher les points
Chaque ligne des données représente une mission, on souhaite afficher de la même couleur les missions qui ont le même type.
Pour cela on filtre les données et utilise la fonction scatter
plusieurs fois, pour chaque type de missions
La couleur des points en fonction du type de mission est définie grâce à factor_cmap
et à la palette de couleur ‘Category10’
cat_unique = df_mission['type_etude'].unique()
for cat in cat_unique:
df_mission_f = df_mission[df_mission['type_etude']==cat]
geo_source = ColumnDataSource(data={
'cat': df_mission_f['type_etude'],
'name': df_mission_f['nom'],
'client': df_mission_f['client'],
'lat': df_mission_f['y'],
'long': df_mission_f['x']
})
p.scatter(x='long', y='lat', size=12, alpha=0.5, source=geo_source,
color=factor_cmap('cat', 'Category10_6', df_mission['type_etude'].unique()),
legend_group='cat')
Parametrer le rendu de la figure
Cosmétique pour masquer l’affichage des axes dont on ne se sert pas.
p.legend.click_policy = "hide"
permet de rendre la légende interactive et de masquer les missions par types.
p.toolbar.active_scroll = p.select_one(WheelZoomTool)
permet d’activer la fonction de zoom avec la souris.
p.xgrid.grid_line_color = None
p.ygrid.grid_line_color = None
p.xaxis.major_label_text_color = None
p.yaxis.major_label_text_color = None
p.xaxis.major_tick_line_color = None
p.xaxis.minor_tick_line_color = None
p.yaxis.major_tick_line_color = None
p.yaxis.minor_tick_line_color = None
p.yaxis.axis_line_color = None
p.xaxis.axis_line_color = None
p.legend.label_text_font_size = "9pt"
p.legend.click_policy = "hide"
p.toolbar.active_scroll = p.select_one(WheelZoomTool)
show(p) #afficher la carte
Enregistrer le HTML de la carte
from bokeh.plotting import output_file, save
output_file('carte_bokeh.html')
save(p)