Pratique de geopandas avec les données vélib

Ce chapitre illustre les fonctionalités de GeoPandas à partir des décomptes de vélo fournis par la ville de Paris en opendata. Il prolonge le chapitre précédent avec des données un petit peu plus complexes à manipuler.

Manipulation
Exercice
Author

Lino Galiana

Published

2024-04-27

Dans ce TP, nous allons apprendre à importer et manipuler des données spatiales avec Python.

Ce langage propose des fonctionnalités très intéressantes pour ce type de données complexes qui le rendent capable de se comporter comme un logiciel de SIG1. Grâce à la librairie Geopandas, une extension de Pandas aux données spatiales, les données géographiques pourront être manipulées comme n’importe quel type de données avec Python. La complexité induite par la dimension spatiale ne sera pas ressentie.

Illustration du principe des données spatiales (documentation de `sf`, l'équivalent de `Geopandas` en `R`) ![](https://user-images.githubusercontent.com/520851/50280460-e35c1880-044c-11e9-9ed7-cc46754e49db.jpg){width="70%"}

Ce chapitre illustre à partir d’exemples pratiques certains principes centraux de l’analyse de données :

Si vous êtes intéressés par R, une version très proche de ce TP est disponible dans ce cours de R.

0.1 Préliminaires

Avant de se lancer dans le TD, il est nécessaire d’installer quelques librairies qui ne sont pas disponibles par défaut, dans l’environnement Python de base de la data science. Pour installer celles-ci depuis une cellule de notebook Jupyter, le code suivant est à exécuter :

!pip install fiona shapely
!pip install pyproj rtree
!pip install contextily
!pip install geopandas
!pip install pygeos
!pip install topojson

Après installations, les packages à importer pour progresser dans ce chapitre sont les suivants :

import geopandas as gpd
import contextily as ctx
import matplotlib.pyplot as plt

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

!pip install requests py7zr geopandas openpyxl tqdm s3fs PyYAML xlrd
!pip install git+https://github.com/inseefrlab/cartiflette
from cartiflette import carti_download

0.2 Lire et enrichir des données spatiales

Dans cette partie, nous utiliserons les fonds de carte de l’IGN dont la mise à disposition est facilitée par le projet cartiflette2.

0.3 Le système de projection

Un concept central dans les logiciels de SIG est la notion de projection. L’exercice précédent imposait parfois certaines projections sans expliquer l’importance de ces choix. Python, comme tout SIG, permet une gestion cohérente des projections.

Observez les variations significatives de proportions pour certains pays selon les projections choisies:

Avec la question 1 illustrant quelques cas pathologiques, on comprend que les projections ont un effet déformant qui se voit bien lorsqu’on les représente côte à côte sous forme de cartes :

(a) Mercator WGS84 (EPSG: 4326)
(b) Projection healpix (+proj=healpix +lon_0=0 +a=1)
(c) Projection prévue pour Tahiti (EPSG: 3304)
(d) Projection Albers prévue pour Etats-Unis (EPSG: 5070)
Figure 1: Comparaison des projections

Cependant le problème n’est pas que visuel, il est également numérique. Les calculs géométriques amènent à des différences assez notables selon le système de référence utilisé.

On peut représenter ces approximations sur une carte3 pour se faire une idée des régions où l’erreur de mesure est la plus importante.

Ce type d’erreur de mesure est normal à l’échelle du territoire français. Les projections héritères du Mercator déforment les distances, surtout lorqu’on se rapproche de l’équateur ou des pôles.

(a) Exemple de reprojection de pays depuis le site thetruesize.com
(b) “Don’t trust the Mercator projection” sur Reddit
Figure 2: La projection Mercator, une vision déformante

Pour aller plus loin, la carte interactive suivante, construite par Nicolas Lambert, issue de ce notebook Observable, illustre l’effet déformant de la projection Mercator, et de quelques-unes autres, sur notre perception de la taille des pays.

Voir la carte interactive

Il n’est donc pas suprenant que nos déformations soient exacerbées aux extrèmes du territoire métropolitain. Si les approximations sont légères sur de petits territoires, les erreurs peuvent être non négligeables à l’échelle de la France.

Il faut donc systématiquement repasser les données dans le système de projection Lambert 93 (le système officiel pour la métropole) avant d’effectuer des calculs géométriques.

0.4 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 en utilisant un URL

url = "https://opendata.paris.fr/explore/dataset/velib-emplacement-des-stations/download/?format=geojson&timezone=Europe/Berlin&lang=fr"

Dans le prochain exercice, nous proposons de créer rapidement une carte comprenant trois couches :

  • Les localisations de stations sous forme de points ;
  • Les bordures des communes et arrondissements pour contextualiser ;
  • Les bordures des départements en traits plus larges pour contextualiser également.

Nous irons plus loin dans le travail cartographique dans le prochain chapitre. Mais être en mesure de positionner rapidement ses données sur une carte est toujours utile dans un travail exploratoire.

En amont de l’exercice, utiliser la fonction suivante du package cartiflette pour récupérer le fonds de carte des départements de la petite couronne:

idf = carti_download(
    values=["11"],
    crs=4326,
    borders="DEPARTEMENT",
    vectorfile_format="geojson",
    filter_by="REGION",
    source="EXPRESS-COG-CARTO-TERRITOIRE",
    year=2022,
)

petite_couronne_departements = idf.loc[
    idf["INSEE_DEP"].isin(["75", "92", "93", "94"])
].to_crs(2154)

La couche de base obtenue à l’issue de la question 4.

Puis en y ajoutant les limites départementales (question 5).

Puis les stations (question 6).

La carte finale, après mise en forme:

0.5 Jointures spatiales

Les jointures attributaires fonctionnent comme avec un Pandas classique. 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 à plusieurs fonctions.

La documentation à laquelle se référer est ici. Une version pédagogique pour R se trouve dans la documentation utilitR.

Carte obtenue à la question 4 :

Avec la carte de la question 4, basée sur des aplats de couleurs (choropleth map), le lecteur est victime d’une illusion classique. Les arrondissements les plus visibles sur la carte sont les plus grands. D’ailleurs c’est assez logique qu’ils soient également mieux pourvus en velib. Même si l’offre de velib est probablement plus reliée à la densité de population et d’équipements, on peut penser que l’effet taille joue et qu’ainsi on est victime d’une illusion avec la carte précédente.

Si on représente plutôt la capacité sous forme de densité, pour tenir compte de la taille différente des arrondissements, les conclusions sont inversées et correspondent mieux aux attentes d’un modèle centre-périphérie. Les arrondissements centraux sont mieux pourvus, cela se voit encore mieux avec des ronds proportionnels plutôt qu’une carte chorolèpthe.

0.6 Exercice supplémentaire

Les exercices précédents ont permis de se familiariser au traitement de données spatiales. Néanmoins il arrive de devoir jongler plus avec la dimension géométrique par exemple pour changer d’échelle ou introduire des fusions/dissolutions de géométries.

Imaginons que chaque utilisateur de velib se déplace exclusivement vers la station la plus proche (à supposer qu’il n’y a jamais pénurie ou surcapacité). Quelle est la carte de la couverture des vélibs ? Pour répondre à ce type de question, on utilise fréquemment la la tesselation de Voronoï, une opération classique pour transformer des points en polygones. L’exercice suivant permet de se familiariser avec cette approche4.

Exercice à venir

Informations additionnelles

environment files have been tested on.

Latest built version: 2024-04-27

Python version used:

'3.11.6 | packaged by conda-forge | (main, Oct  3 2023, 10:40:35) [GCC 12.3.0]'
Package Version
affine 2.4.0
aiobotocore 2.12.2
aiohttp 3.9.3
aioitertools 0.11.0
aiosignal 1.3.1
alembic 1.13.1
aniso8601 9.0.1
annotated-types 0.6.0
appdirs 1.4.4
archspec 0.2.3
astroid 3.1.0
asttokens 2.4.1
attrs 23.2.0
Babel 2.14.0
bcrypt 4.1.2
beautifulsoup4 4.12.3
black 24.4.2
blinker 1.7.0
blis 0.7.11
bokeh 3.4.0
boltons 23.1.1
boto3 1.34.51
botocore 1.34.51
branca 0.7.1
Brotli 1.1.0
cachetools 5.3.3
cartiflette 0.0.2
Cartopy 0.23.0
catalogue 2.0.10
cattrs 23.2.3
certifi 2024.2.2
cffi 1.16.0
charset-normalizer 3.3.2
click 8.1.7
click-plugins 1.1.1
cligj 0.7.2
cloudpathlib 0.16.0
cloudpickle 3.0.0
colorama 0.4.6
comm 0.2.2
commonmark 0.9.1
conda 24.3.0
conda-libmamba-solver 24.1.0
conda-package-handling 2.2.0
conda_package_streaming 0.9.0
confection 0.1.4
contextily 1.6.0
contourpy 1.2.1
cryptography 42.0.5
cycler 0.12.1
cymem 2.0.8
cytoolz 0.12.3
dask 2024.4.1
dask-expr 1.0.10
debugpy 1.8.1
decorator 5.1.1
dill 0.3.8
distributed 2024.4.1
distro 1.9.0
docker 7.0.0
duckdb 0.10.1
en-core-web-sm 3.7.1
entrypoints 0.4
et-xmlfile 1.1.0
exceptiongroup 1.2.0
executing 2.0.1
fastjsonschema 2.19.1
fiona 1.9.6
flake8 7.0.0
Flask 3.0.2
folium 0.16.0
fontawesomefree 6.5.1
fonttools 4.51.0
frozenlist 1.4.1
fsspec 2023.12.2
GDAL 3.8.4
gensim 4.3.2
geographiclib 2.0
geopandas 0.12.2
geoplot 0.5.1
geopy 2.4.1
gitdb 4.0.11
GitPython 3.1.43
google-auth 2.29.0
graphene 3.3
graphql-core 3.2.3
graphql-relay 3.2.0
graphviz 0.20.3
great-tables 0.5.0
greenlet 3.0.3
gunicorn 21.2.0
htmltools 0.5.1
hvac 2.1.0
idna 3.6
imageio 2.34.1
importlib_metadata 7.1.0
importlib_resources 6.4.0
inflate64 1.0.0
ipykernel 6.29.3
ipython 8.22.2
ipywidgets 8.1.2
isort 5.13.2
itsdangerous 2.1.2
jedi 0.19.1
Jinja2 3.1.3
jmespath 1.0.1
joblib 1.3.2
jsonpatch 1.33
jsonpointer 2.4
jsonschema 4.21.1
jsonschema-specifications 2023.12.1
jupyter-cache 1.0.0
jupyter_client 8.6.1
jupyter_core 5.7.2
jupyterlab_widgets 3.0.10
kaleido 0.2.1
kiwisolver 1.4.5
kubernetes 29.0.0
langcodes 3.4.0
language_data 1.2.0
lazy_loader 0.4
libmambapy 1.5.7
llvmlite 0.42.0
locket 1.0.0
lxml 5.2.1
lz4 4.3.3
Mako 1.3.2
mamba 1.5.7
mapclassify 2.6.1
marisa-trie 1.1.0
Markdown 3.6
MarkupSafe 2.1.5
matplotlib 3.8.3
matplotlib-inline 0.1.6
mccabe 0.7.0
menuinst 2.0.2
mercantile 1.2.1
mizani 0.11.2
mlflow 2.11.3
mlflow-skinny 2.11.3
msgpack 1.0.7
multidict 6.0.5
multivolumefile 0.2.3
munkres 1.1.4
murmurhash 1.0.10
mypy 1.9.0
mypy-extensions 1.0.0
nbclient 0.10.0
nbformat 5.10.4
nest_asyncio 1.6.0
networkx 3.3
nltk 3.8.1
numba 0.59.1
numpy 1.26.4
oauthlib 3.2.2
opencv-python-headless 4.9.0.80
openpyxl 3.1.2
OWSLib 0.28.1
packaging 23.2
pandas 2.2.1
paramiko 3.4.0
parso 0.8.4
partd 1.4.1
pathspec 0.12.1
patsy 0.5.6
Pebble 5.0.7
pexpect 4.9.0
pickleshare 0.7.5
pillow 10.3.0
pip 24.0
pkgutil_resolve_name 1.3.10
platformdirs 4.2.0
plotly 5.19.0
plotnine 0.13.5
pluggy 1.4.0
polars 0.20.18
preshed 3.0.9
prometheus_client 0.20.0
prometheus-flask-exporter 0.23.0
prompt-toolkit 3.0.42
protobuf 4.25.3
psutil 5.9.8
ptyprocess 0.7.0
pure-eval 0.2.2
py7zr 0.20.8
pyarrow 15.0.0
pyarrow-hotfix 0.6
pyasn1 0.5.1
pyasn1-modules 0.3.0
pybcj 1.0.2
pycodestyle 2.11.1
pycosat 0.6.6
pycparser 2.21
pycryptodomex 3.20.0
pydantic 2.7.1
pydantic_core 2.18.2
pyflakes 3.2.0
Pygments 2.17.2
PyJWT 2.8.0
pylint 3.1.0
PyNaCl 1.5.0
pynsee 0.1.7
pyOpenSSL 24.0.0
pyparsing 3.1.2
pyppmd 1.1.0
pyproj 3.6.1
pyshp 2.3.1
PySocks 1.7.1
python-dateutil 2.9.0
python-dotenv 1.0.1
python-magic 0.4.27
pytz 2024.1
pyu2f 0.1.5
pywaffle 1.1.0
PyYAML 6.0.1
pyzmq 25.1.2
pyzstd 0.15.10
QtPy 2.4.1
querystring-parser 1.2.4
rasterio 1.3.10
referencing 0.34.0
regex 2023.12.25
requests 2.31.0
requests-cache 1.2.0
requests-oauthlib 2.0.0
rpds-py 0.18.0
rsa 4.9
Rtree 1.2.0
ruamel.yaml 0.18.6
ruamel.yaml.clib 0.2.8
s3fs 2023.12.2
s3transfer 0.10.1
scikit-image 0.23.2
scikit-learn 1.4.1.post1
scipy 1.13.0
seaborn 0.13.2
setuptools 69.2.0
shapely 2.0.3
six 1.16.0
smart-open 6.4.0
smmap 5.0.0
snuggs 1.4.7
sortedcontainers 2.4.0
soupsieve 2.5
spacy 3.7.4
spacy-legacy 3.0.12
spacy-loggers 1.0.5
SQLAlchemy 2.0.29
sqlparse 0.4.4
srsly 2.4.8
stack-data 0.6.2
statsmodels 0.14.1
tabulate 0.9.0
tblib 3.0.0
tenacity 8.2.3
texttable 1.7.0
thinc 8.2.3
threadpoolctl 3.4.0
tifffile 2024.4.24
tomli 2.0.1
tomlkit 0.12.4
toolz 0.12.1
topojson 1.8
tornado 6.4
tqdm 4.66.2
traitlets 5.14.2
truststore 0.8.0
typer 0.9.4
typing_extensions 4.11.0
tzdata 2024.1
Unidecode 1.3.8
url-normalize 1.4.3
urllib3 1.26.18
wasabi 1.1.2
wcwidth 0.2.13
weasel 0.3.4
webcolors 1.13
webdriver-manager 4.0.1
websocket-client 1.7.0
Werkzeug 3.0.2
wheel 0.43.0
widgetsnbextension 4.0.10
wordcloud 1.9.3
wrapt 1.16.0
xgboost 2.0.3
xlrd 2.0.1
xyzservices 2024.4.0
yarl 1.9.4
yellowbrick 1.5
zict 3.0.0
zipp 3.17.0
zstandard 0.22.0

View file history

SHA Date Author Description
c80ffa8 2024-04-06 16:12:43 linogaliana Problem with geopandas
3f7fff1 2024-04-06 13:55:28 Lino Galiana Update 03_geopandas_TP.qmd
e57f9cc 2024-04-06 13:12:25 Lino Galiana Retire commentaire inutile
8c316d0 2024-04-05 19:00:59 Lino Galiana Fix cartiflette deprecated snippets (#487)
ce33d5d 2024-01-16 15:47:22 Lino Galiana Adapte les exemples de code de cartiflette (#482)
005d89b 2023-12-20 17:23:04 Lino Galiana Finalise l’affichage des statistiques Git (#478)
3fba612 2023-12-17 18:16:42 Lino Galiana Remove some badges from python (#476)
1f23de2 2023-12-01 17:25:36 Lino Galiana Stockage des images sur S3 (#466)
09654c7 2023-11-14 15:16:44 Antoine Palazzolo Suggestions Git & Visualisation (#449)
889a71b 2023-11-10 11:40:51 Antoine Palazzolo Modification TP 3 (#443)
8728352 2023-10-24 11:50:08 Lino Galiana Correction coquilles geopandas (#444)
8071bbb 2023-10-23 17:43:37 tomseimandi Make minor changes to 02b, 03, 04a (#440)
102ce9f 2023-10-22 11:39:37 Thomas Faria Relecture Thomas, première partie (#438)
e918be6 2023-10-09 12:39:31 linogaliana change featured
f8831e7 2023-10-09 10:53:34 Lino Galiana Relecture antuki geopandas (#429)
20432f7 2023-09-27 15:31:22 Lino Galiana Restructure le TP GeoPandas (#414)
338c07e 2023-09-26 13:44:45 linogaliana eval false
154f09e 2023-09-26 14:59:11 Antoine Palazzolo Des typos corrigées par Antoine (#411)
a8f90c2 2023-08-28 09:26:12 Lino Galiana Update featured paths (#396)
3bdf3b0 2023-08-25 11:23:02 Lino Galiana Simplification de la structure 🤓 (#393)
130ed71 2023-07-18 19:37:11 Lino Galiana Restructure les titres (#374)
ef28fef 2023-07-07 08:14:42 Lino Galiana Listing pour la première partie (#369)
f21a24d 2023-07-02 10:58:15 Lino Galiana Pipeline Quarto & Pages 🚀 (#365)
bdf396d 2023-06-11 17:22:29 Lino Galiana update geopandas part for pandas v2 (#360)
3912a7e 2023-02-07 17:18:25 Lino Galiana Back to IGN provider (#350)
3b8715e 2022-12-11 18:52:23 Lino Galiana TP geopandas (#333)
2e215a9 2022-10-28 14:35:09 Lino Galiana Solve problem geopandas TP (#309)
f394b23 2022-10-13 14:32:05 Lino Galiana Dernieres modifs geopandas (#298)
af763cc 2022-10-12 10:17:56 Lino Galiana Reprise exercice geopandas (#294)
f10815b 2022-08-25 16:00:03 Lino Galiana Notebooks should now look more beautiful (#260)
494a85a 2022-08-05 14:49:56 Lino Galiana Images featured ✨ (#252)
d201e3c 2022-08-03 15:50:34 Lino Galiana Pimp la homepage ✨ (#249)
12965ba 2022-05-25 15:53:27 Lino Galiana :launch: Bascule vers quarto (#226)
9c71d6e 2022-03-08 10:34:26 Lino Galiana Plus d’éléments sur S3 (#218)
6777f03 2021-10-29 09:38:09 Lino Galiana Notebooks corrections (#171)
2a8809f 2021-10-27 12:05:34 Lino Galiana Simplification des hooks pour gagner en flexibilité et clarté (#166)
735e677 2021-10-19 09:46:12 Lino Galiana Règle problème des cartes qui s’affichent pas (#165)
5ad057f 2021-10-10 15:13:16 Lino Galiana Relectures pandas & geopandas (#159)
2e4d586 2021-09-02 12:03:39 Lino Galiana Simplify badges generation (#130)
80877d2 2021-06-28 11:34:24 Lino Galiana Ajout d’un exercice de NLP à partir openfood database (#98)
4cdb759 2021-05-12 10:37:23 Lino Galiana :sparkles: :star2: Nouveau thème hugo :snake: :fire: (#105)
7f9f97b 2021-04-30 21:44:04 Lino Galiana 🐳 + 🐍 New workflow (docker 🐳) and new dataset for modelization (2020 🇺🇸 elections) (#99)
6d010fa 2020-09-29 18:45:34 Lino Galiana Simplifie l’arborescence du site, partie 1 (#57)
66f9f87 2020-09-24 19:23:04 Lino Galiana Introduction des figures générées par python dans le site (#52)
badc492 2020-09-22 18:36:33 Lino Galiana Finalize geopandas section (#48)
15b7dad 2020-09-18 11:03:41 Lino Galiana Finalisation TP geopandas (#33)
ffb05cf 2020-09-10 17:18:15 Lino Galiana Partie sur les données spatiales (#20) :warning: pas fini
Back to top

Footnotes

  1. D’ailleurs, le logiciel de cartographie spécialisé QGIS, s’appuie sur Python pour les manipulations de données nécessaires avant de réaliser une carte.↩︎

  2. La librairie Python est encore expérimentale mais les prochaines semaines devraient permettre de combler ce manque. Une documentation interactive illustrant le code nécessaire pour reproduire telle ou telle carte est disponible sur linogaliana.github.io/cartiflette-website.↩︎

  3. Cette carte n’est pas trop soignée, c’est normal nous verrons comment faire de belles cartes ultérieurement.↩︎

  4. Dans ce document de travail sur données de téléphonie mobile, on montre néanmoins que cette approche n’est pas sans biais sur des phénomènes où l’hypothèse de proximité spatiale est trop simplificatrice.↩︎

Citation

BibTeX citation:
@book{galiana2023,
  author = {Galiana, Lino},
  title = {Python Pour La Data Science},
  date = {2023},
  url = {https://pythonds.linogaliana.fr/},
  doi = {10.5281/zenodo.8229676},
  langid = {en}
}
For attribution, please cite this work as:
Galiana, Lino. 2023. Python Pour La Data Science. https://doi.org/10.5281/zenodo.8229676.