Pratique de geopandas avec les données vélib

Download nbviewer Onyxia
Binder Open In Colab githubdev

Installations préalables :

!pip install pandas fiona shapely pyproj rtree # à faire obligatoirement en premier pour utiliser rtree ou pygeos pour les jointures spatiales
!pip install contextily
!pip install geopandas
!pip install pygeos

Les instructions d’installation du package cartiflette sont quant à elles détaillées dans le chapitre précédent.

import geopandas as gpd

Lire et enrichir des données spatiales

Dans cette partie, nous utiliserons le package cartiflette qui facilite la récupération de contours de cartes. Une version antérieure de cet exercice, présentée sous forme d’exercice supplémentaire 👇️, utilisait des fonds de carte issus de data.gouv.

/src/cartiflette/cartiflette/download/dev.py:153: SyntaxWarning:

"is" with a literal. Did you mean "=="?

:::

ID NOM NOM_M INSEE_COM STATUT POPULATION INSEE_CAN INSEE_ARR INSEE_DEP INSEE_REG SIREN_EPCI geometry
0 COMMUNE_0000000009736048 Paris PARIS 75056 Capitale d'état 2165423 NR 1 75 11 200054781 POLYGON ((2.36420 48.81640, 2.36333 48.81615, ...
0 COMMUNE_0000000009736037 Levallois-Perret LEVALLOIS-PERRET 92044 Commune simple 66082 16 2 92 11 200054781/200057982 POLYGON ((2.28739 48.90364, 2.28846 48.90302, ...
1 COMMUNE_0000000009736055 Bois-Colombes BOIS-COLOMBES 92009 Commune simple 28841 11 2 92 11 200054781/200057990 POLYGON ((2.26639 48.90629, 2.26645 48.90615, ...
2 COMMUNE_0000000009736538 Malakoff MALAKOFF 92046 Commune simple 30950 18 1 92 11 200054781/200057966 POLYGON ((2.27818 48.81425, 2.28066 48.81469, ...
3 COMMUNE_0000000009736038 Clichy CLICHY 92024 Commune simple 63089 09 2 92 11 200054781/200057990 POLYGON ((2.30377 48.89415, 2.30258 48.89487, ...
<Geographic 2D CRS: EPSG:4326>
Name: WGS 84
Axis Info [ellipsoidal]:
- Lat[north]: Geodetic latitude (degree)
- Lon[east]: Geodetic longitude (degree)
Area of Use:
- name: World.
- bounds: (-180.0, -90.0, 180.0, 90.0)
Datum: World Geodetic System 1984 ensemble
- Ellipsoid: WGS 84
- Prime Meridian: Greenwich

La carte du 92 est la suivante:

Quant à Paris, à l’issue de la question 5, la carte aura l’aspect suivant:

En effet, on ne dispose ainsi pas des limites des arrondissements parisiens, ce qui appauvrit grandement la carte de Paris. On pourrait les récupérer directement depuis le site d’open-data du Grand Paris, ce qui est proposé en exercice supplémentaire 👇️. On propose ici d’utiliser à nouveau cartiflette pour cela afin de disposer du fonds de carte officiel.

La carte de Paris intra-muros est, après la récupération des arrondissements avec cartiflette de ce type là:

epsg:4326
epsg:2154
False

La carte obtenue à l’issue de la question 6, c’est-à-dire après avoir consolidé les données, devrait avoir l’aspect suivant:

Utiliser des données géographiques comme des couches graphiques

Souvent, le découpage communal ne sert qu’en fond de cartes, pour donner des repères. En complément de celui-ci, on peut désirer exploiter un autre jeu de données.

On va partir des données de localisation des stations velib, disponibles sur le site d’open data de la ville de Paris et requêtables directement par l’url https://opendata.paris.fr/explore/dataset/velib-emplacement-des-stations/download/?format=geojson&timezone=Europe/Berlin&lang=fr

capacity name stationcode geometry
0 21 Toudouze - Clauzel 9020 POINT (2.33736 48.87930)
1 24 Théâtre des Amandiers - Palais des sports 92002 POINT (2.21369 48.89265)
2 14 Abbeville - Faubourg Poissonnière 9002 POINT (2.34915 48.87922)
3 24 Quai de la Seine 19003 POINT (2.37039 48.88449)
4 46 Saint-Maur - Roquette 11023 POINT (2.38355 48.85869)

La carte attendu à l’issue de la question 3 a l’aspect suivant:

Text(0.5, 1.0, 'Les 50 principales stations de Vélib')
['TRAMWAY' 'RER' 'TRAIN' 'TER' 'NAVETTE' 'METRO' 'RER C']

L’ajout du réseau de métro permet d’obtenir une carte ressemblant à celle-ci:

Text(0.5, 1.0, 'Les 50 principales stations de Vélib')

Pour faire une belle carte, il faudrait couper les lignes de métro via une jointure spatiale ou utiliser un fonds de carte conceptuel. L’exercice suivant propose de mettre en oeuvre la deuxième méthode. La première est proposée en exercice supplémentaire 👇️.

Par exemple, en utilisant le fond Stamen.Watercolor, on obtient la carte suivante. Celle-ci permet déjà de mieux localiser les stations.

Jointures spatiales

Les jointures attributaires fonctionnent comme avec un DataFrame pandas. Pour conserver un objet spatial in fine, il faut faire attention à utiliser en premier (base de gauche) l’objet GeoPandas. En revanche, l’un des intérêts des objets geopandas est qu’on peut également faire une jointure sur la dimension spatiale grâce à sjoin.

La documentation à laquelle se référer est ici.

capacity name stationcode geometry index_right ID NOM NOM_M INSEE_COM STATUT POPULATION INSEE_CAN INSEE_ARR INSEE_DEP INSEE_REG SIREN_EPCI INSEE_ARM
0 21 Toudouze - Clauzel 9020 POINT (2.33736 48.87930) 5 ARR_MUNI0000000009736043 Paris 9e Arrondissement PARIS 9E ARRONDISSEMENT 75056 NaN 60026 NaN NaN 75 NaN NaN 75109
2 14 Abbeville - Faubourg Poissonnière 9002 POINT (2.34915 48.87922) 5 ARR_MUNI0000000009736043 Paris 9e Arrondissement PARIS 9E ARRONDISSEMENT 75056 NaN 60026 NaN NaN 75 NaN NaN 75109
37 17 Choron - Martyrs 9016 POINT (2.33967 48.87785) 5 ARR_MUNI0000000009736043 Paris 9e Arrondissement PARIS 9E ARRONDISSEMENT 75056 NaN 60026 NaN NaN 75 NaN NaN 75109
42 22 Godot de Mauroy - Madeleine 9034 POINT (2.32635 48.86979) 5 ARR_MUNI0000000009736043 Paris 9e Arrondissement PARIS 9E ARRONDISSEMENT 75056 NaN 60026 NaN NaN 75 NaN NaN 75109
70 14 Boudreau - Auber 9106 POINT (2.32942 48.87219) 5 ARR_MUNI0000000009736043 Paris 9e Arrondissement PARIS 9E ARRONDISSEMENT 75056 NaN 60026 NaN NaN 75 NaN NaN 75109

Pour la question 2, la première méthode consiste à afficher toute la ville mais à ne représenter que les points des stations du 19e:

<AxesSubplot: >

Néanmoins, il est préférable de se centrer sur le 19e en premier lieu, ce qui donne une carte comme celle-ci:

ID NOM NOM_M INSEE_COM STATUT POPULATION INSEE_CAN INSEE_ARR INSEE_DEP INSEE_REG SIREN_EPCI geometry INSEE_ARM stationcode capacity
0 COMMUNE_0000000009736037 Levallois-Perret LEVALLOIS-PERRET 92044 Commune simple 66082 16 2 92 11 200054781/200057982 POLYGON ((2.28739 48.90364, 2.28846 48.90302, ... NaN 11 359
1 COMMUNE_0000000009736055 Bois-Colombes BOIS-COLOMBES 92009 Commune simple 28841 11 2 92 11 200054781/200057990 POLYGON ((2.26639 48.90629, 2.26645 48.90615, ... NaN 2 60
2 COMMUNE_0000000009736538 Malakoff MALAKOFF 92046 Commune simple 30950 18 1 92 11 200054781/200057966 POLYGON ((2.27818 48.81425, 2.28066 48.81469, ... NaN 8 238
3 COMMUNE_0000000009736038 Clichy CLICHY 92024 Commune simple 63089 09 2 92 11 200054781/200057990 POLYGON ((2.30377 48.89415, 2.30258 48.89487, ... NaN 13 422
4 COMMUNE_0000000009736052 Nanterre NANTERRE 92050 Préfecture 96277 99 2 92 11 200054781/200057982 POLYGON ((2.22910 48.90603, 2.23037 48.90377, ... NaN 8 222

La carte des places disponibles est celle-ci:

Text(0.5, 1.0, 'Nombre de places disponibles')

Alors que la carte des capacités de stations est plutôt celle-là:

Text(0.5, 1.0, 'Nombre de stations')

Pas vraiment de différence marquée entre les deux, on peut se contenter de regarder la capacité.

Enfin, dans la question 4, si on représente plutôt la capacité sous forme de densité, pour tenir compte de la taille différente des arrondissements, on obtient cette carte:

<AxesSubplot: >

Avec une palette plasma_r, cela donne plutôt cette carte:

<AxesSubplot: >

Avec un peu de travail sur l’esthétique, la carte que vous obtenez à l’issue de l’exercice ressemble à celle-ci:

Trouver les toilettes publiques les plus proches

Objectif

Jusqu’à présent, nous nous sommes familiarisés avec la manipulation de données spatiales et la représentation rapide de celle-ci grâce aux fonctionalités de GeoPandas.

A partir de maintenant, nous allons utiliser GeoPandas pour des tâches de manipulation géométrique.
Ces opérations reposeront sur des tâches classiques de la géomatique qui sont facilitées par le fait que GeoPandas offre une surcouche au package Shapely de la même manière que Pandas était une sur-couche de Numpy pour les opérations numériques.

L’exemple suivant permet d’illustrer le principe d’une des opérations que nous allons utiliser, à savoir la recherche de plus proche point:

from shapely.ops import Polygon
from shapely.ops import nearest_points
triangle = Polygon([(0, 0), (1, 0), (0.5, 1), (0, 0)])
square = Polygon([(0, 2), (1, 2), (1, 3), (0, 3), (0, 2)])
[o.wkt for o in nearest_points(triangle, square)]
['POINT (0.5 1)', 'POINT (0.5 2)']

GeoPandas va permettre de généraliser ce processus en utilisant non plus deux listes modifiées (les polygones de Shapely) mais des DataFrames géographiques. Cela permettra, au passage, d’enrichir les jointures spatiales avec les attributs des DataFrames concernés.

Sur Shapely, vous pourrez trouver une aide ici. Néanmoins, à mesure que GeoPandas se développe, il devient de moins en moins nécessaire d’utiliser directement Shapely.

Mise en application

Nous allons rechercher les toilettes publiques les plus proches de chaque station. Sans les fonctionalités de GeoPandas, cette recherche serait assez pénible.

Le jeu de données open-data des toilettes publiques présente l’aspect suivant:

accessible_au_public acces_bouton_poussoir tarif_gratuit_payant accessibilite_pmr gestionnaire ligne acces_passe_navigo_ou_ticket_t localisation en_zone_controlee station hors_zone_controlee_station hors_zone_controlee_voie_publique geometry
0 None None None None Toilette publique RATP 4 None Il est accessible depuis le guichet au niveau ... None Bagneux Lucie Aubrac None None POINT (2.31740 48.80357)
1 oui None payant oui Toilette publique RATP 10 oui Sortie 2 boulevard St-Germain, à proximité du ... None Cluny - La Sorbonne None None POINT (2.34503 48.85080)

Les toilettes les plus proches d’Edgar Quinet sont les suivantes:

localisation station name distance
564 Sur le quai ligne B, en direction de Saint-Rém... Denfert-Rochereau Gare Montparnasse - Edgar Quinet 1177.501002
1183 Sur le quai ligne B, en direction de Saint-Rém... Denfert-Rochereau Edgar Quinet - Raspail 737.660246
1191 Sur le quai ligne B, en direction de Saint-Rém... Denfert-Rochereau Edgar Quinet - Gaité 1091.971078

Il va donc falloir se retenir un peu car s’agit de toilettes situées à la station Denfert Rochereau !

Enfin, de manière plus globale, voici la distribution des distances aux toilettes les plus proches:

<AxesSubplot: ylabel='Frequency'>

Le mode de la distribution est entre 1 et 2 km, ce qui est une petite distance tout de même ! C’est normal, il ne s’agit pas de l’ensemble des toilettes publiques de la ville de Paris mais de celles gérées par la RATP. Rassurez-vous, au moins dans Paris intra-muros, vous n’avez pas à systématiquement marcher (ou rouler) autant.

Exercices supplémentaires

Voici une fonction pour télécharger et dézipper facilement un fonds de carte issu de data.gouv

import requests
import tempfile
import zipfile

temporary_location = tempfile.gettempdir()

def download_unzip(url, dirname = tempfile.gettempdir(), destname = "borders"):
  myfile = requests.get(url)
  open("{}/{}.zip".format(dirname, destname), 'wb').write(myfile.content)
  with zipfile.ZipFile("{}/{}.zip".format(dirname, destname), 'r') as zip_ref:
      zip_ref.extractall(dirname + '/' + destname)
<AxesSubplot: >
epsg:4326
False

/tmp/ipykernel_1031/349994121.py:6: FutureWarning:

The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.

ID NOM NOM_M INSEE_COM STATUT POPULATION INSEE_CAN INSEE_ARR INSEE_DEP INSEE_REG SIREN_EPCI geometry c_ar l_aroff surface l_ar n_sq_co n_sq_ar perimetre
18 NaN NaN NaN NaN NaN NaN NaN NaN 75 NaN NaN POLYGON ((653665.113 6861929.286, 653699.365 6... 4.0 Hôtel-de-Ville 1.600586e+06 4ème Ardt 750001537.0 750000004.0 5420.908434
19 NaN NaN NaN NaN NaN NaN NaN NaN 75 NaN NaN POLYGON ((656928.376 6864099.214, 656933.359 6... 20.0 Ménilmontant 5.983446e+06 20ème Ardt 750001537.0 750000020.0 10704.940486

Jointures spatiales

L’objectif de cet exercice est de ne conserver que les lignes de transports à l’intérieur de Paris intra-muros. Il s’agit d’appliquer les jointures spatiales de manière un petit peu différente à précédemment.

:::

La carte obtenue aura l’aspect suivant:

/miniconda/envs/python-ENSAE/lib/python3.9/site-packages/geopandas/plotting.py:693: UserWarning:

The GeoDataFrame you are attempting to plot is empty. Nothing has been displayed.

<AxesSubplot: >

Error in callback <function _draw_all_if_interactive at 0x7fe67c037f70> (for post_execute):

ValueError: cannot convert float NaN to integer

ValueError: cannot convert float NaN to integer

<Figure size 768x480 with 1 Axes>

Cette fois, on a bien conservé que les lignes de transport dans Paris. Un peu de travail sur le rendu serait nécessaire pour obtenir une belle carte. Vous pouvez le faire en exercice, après avoir consulté le chapitre relatif à la cartographie dans la partie visualisation de données.

Previous
Next