un mot sur folium#

à télécharger

pour exécuter ce notebook sur votre ordi, commencez par télécharger le zip

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
Make this Notebook Trusted to load map: File -> Trust Notebook

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)
n_sq_ar c_ar c_arinsee l_ar l_aroff n_sq_co surface perimetre geometry
0 750000011 11 75111 11ème Ardt Popincourt 750001537 3.665442e+06 8282.011886 POLYGON ((2.39624 48.85415, 2.39708 48.85308, ...
1 750000013 13 75113 13ème Ardt Gobelins 750001537 7.149311e+06 11546.546526 POLYGON ((2.37491 48.83801, 2.37698 48.8361, 2...
# pour afficher cela

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

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

map
Make this Notebook Trusted to load map: File -> Trust Notebook

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()
Make this Notebook Trusted to load map: File -> Trust Notebook

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()
stationcode name is_installed capacity numdocksavailable numbikesavailable mechanical ebike is_renting is_returning duedate nom_arrondissement_communes code_insee_commune geometry
0 31104 Mairie de Rosny-sous-Bois OUI 30 3 26 3 23 OUI OUI 2023-10-30 14:23:05+00:00 Rosny-sous-Bois None POINT (2.48658 48.87126)
1 16107 Benjamin Godard - Victor Hugo OUI 35 13 22 16 6 OUI OUI 2023-10-30 14:21:48+00:00 Paris None POINT (2.27572 48.86598)
2 44015 Rouget de L'isle - Watteau OUI 20 18 2 1 1 OUI OUI 2023-10-30 14:20:28+00:00 Vitry-sur-Seine None POINT (2.3963 48.77819)
3 9020 Toudouze - Clauzel OUI 21 16 5 1 4 OUI OUI 2023-10-30 14:19:19+00:00 Paris None POINT (2.33736 48.8793)
4 12109 Mairie du 12ème OUI 30 26 3 1 2 OUI OUI 2023-10-30 14:23:57+00:00 Paris None POINT (2.38755 48.84086)

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
Make this Notebook Trusted to load map: File -> Trust Notebook

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
Make this Notebook Trusted to load map: File -> Trust Notebook

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")