Skip to article frontmatterSkip to article content

la bibliothèque folium (https://python-visualization.github.io/folium/latest/) est un utilitaire qui permet de dessiner des cartes géographiques

elle est donc souvent utilisée en conjonction avec geopandas

les bases

nous allons voir un exemple simplissime qui consiste à afficher des points sur une carte

une carte

et pour commencer on doit créer un objet carte

import folium

# si on veut on peut ne rien préciser du tout
# mais nous on va se centrer sur Paris

PARIS = 48.856542, 2.347614

map = folium.Map(
    location=PARIS,
    zoom_start=5,
    width=500,
    height=300,
)
map
Loading...

des zones

on peut facilement afficher des zones; par exemple affichons les arrondissements de Paris

et après cela je peux faire tout simplement ceci

import geopandas as gpd

arrondissements = gpd.read_file("data/arrondissements.zip", encoding="utf-8")

# accessoirement ceci est une geo dataframe
type(arrondissements)
geopandas.geodataframe.GeoDataFrame
arrondissements.columns
Index(['n_sq_ar', 'c_ar', 'c_arinsee', 'l_ar', 'l_aroff', 'n_sq_co', 'surface', 'perimetre', 'geometry'], dtype='object')
arrondissements.head(2)
Loading...
# pour afficher cela

map = folium.Map(
    location=PARIS,
    zoom_start=12,
)

folium.GeoJson(
    data=arrondissements,
).add_to(map)

map
Loading...

naturellement on peut aussi, en compliquant un petit peu, mettre des couleurs différentes, ajouter des tooltips, etc..

par exemple:

# générateur de couleur

import random

def random_color():
    def randbyte():
        return f"{random.randint(0, 255):02x}"
    return f"#{randbyte()}{randbyte()}{randbyte()}"

# on associe une couleur à chaque arrondissement
arrondissements['color'] = arrondissements.geometry.map(lambda x: random_color())
# pour ajouter des zones

def paris_map():

    map = folium.Map(
        location=PARIS,
        zoom_start=11,
    )
    
    folium.GeoJson(
        data=arrondissements,
        style_function=lambda x: {"color": x["properties"]["color"]},
        tooltip=folium.GeoJsonTooltip(
            fields=["l_ar", "l_aroff"],
            aliases=["nom", "label"],
        )
    ).add_to(map)
    
    return map

paris_map()
Loading...

des marqueurs

pour trouver des données à afficher je retoourne ici <opendata.paris.fr/explore/dataset/velib-disponibilite-en-temps-reel/export>

et cette fois je download au format GeoJson; les données sont mises à jour en temps réel, mais ce n’est pas important

velibs = gpd.read_file("data/velib-disponibilite-en-temps-reel.geojson")
velibs.head()
Loading...

pour ajouter tous ces points, la démarche est à peu près la même que pour les arrondissements; sauf que si on le fait naïvement on tombe sur une erreur - apparemment folium n’aime pas les colonnes de type datetime64, on va l’enlever

# pour contourner une erreur signalée par folium avec les timestamps
# go figure...

if 'duedate' in velibs.columns:
    velibs = velibs.drop(columns=['duedate'])
# on ne voit pas grand-chose avec le look par défaut
# trops de points, les marques sont trop grosses

map = paris_map()

folium.GeoJson(
    data=velibs,
).add_to(map)

map
Loading...

et ici aussi on peut affiner un peu et customiser le look de chaque point; on choisit de mettre un point avec une taille qui dépend du nombre de vélos disponibles

# pour ajouter des marques

map = paris_map()

folium.GeoJson(
    data=velibs,
    # on choisit le type de marker
    marker=folium.CircleMarker(),
    # et les attributs sont calculés ici
    style_function=lambda x: dict(
        color="black",
        radius=1 if not x["properties"]["capacity"]
               else 2 + 4 * (x["properties"]["numbikesavailable"]
                       /x["properties"]["capacity"])
    ),
    # on peut aussi mettre des tooltips...
    tooltip=folium.GeoJsonTooltip(
        fields=['name', 'numbikesavailable', 'capacity'],
        aliases=['nom', 'vélos dispos', 'total'],
    ),
).add_to(map)

map
Loading...

on peut sauver la carte !

une dernière feature très pratique, c’est qu’une fois la carte créée, on peut la sauver au format html standalone (plus besoin de python ni de jupyter pour l’utiliser, le fichier se charge dans un browser web)

# après l'avoir créé, ouvrez le fichier dans le browser

map.save("my-map.html")