Une partie essentielle du travail du data scientist est d’être en mesure de synthétiser une information dans des représentations graphiques percutantes. Ce chapitre permet de découvrir les fonctionalités graphiques de matplotlib, seaborn et plotly pour représenter des statistiques sur les décomptes de vélo à Paris.

Author

Lino Galiana

Published

July 14, 2023

Download nbviewer Onyxia Onyxia
Binder Open In Colab githubdev

La pratique de la visualisation se fera, dans ce cours, en répliquant des graphiques qu’on peut trouver sur la page de l’open data de la ville de Paris ici.

Ce TP vise à initier :

Nous verrons par la suite la manière de construire des cartes facilement avec des formats équivalents.

Si vous êtes intéressés par R , une version très proche de ce TP est disponible dans ce cours d’introduction à R pour l’ENS.

Données

Un sous-ensemble des données de Paris Open Data a été mis à disposition pour faciliter l’import. Il s’agit d’une extraction, qui commence à dater, des données disponibles sur le site où seules les colonnes qui servent à cet exercice ont été conservées.

Premières productions graphiques avec l’API Matplotlib de Pandas

Chercher à produire une visualisation parfaite du premier coup est illusoire. Il est beaucoup plus réaliste d’améliorer graduellement une représentation graphique afin, petit à petit, de mettre en avant les effets de structure dans un jeu de données.

Nous allons donc commencer par nous représenter la distribution des passages aux principales stations de mesure. Pour cela nous allons produire rapidement un barplot puis l’améliorer graduellement.

Dans cette partie, nous allons ainsi reproduire les deux premiers graphiques de la page d’analyse des données : Les 10 compteurs avec la moyenne horaire la plus élevée et Les 10 compteurs ayant comptabilisé le plus de vélos. Les valeurs chiffrées des graphiques seront différentes de celles de la page en ligne, c’est normal, nous travaillons sur des données plus anciennes.

Premières lignes nécessaires pour cet exercice :
Identifiant du compteur Nom du compteur Identifiant du site de comptage Nom du site de comptage Comptage horaire Date et heure de comptage Date d'installation du site de comptage
0 100003096-SC 97 avenue Denfert Rochereau SO-NE 100003096 97 avenue Denfert Rochereau SO-NE 1 2019-08-01T02:00:00Z 2012-02-22
1 100003096-SC 97 avenue Denfert Rochereau SO-NE 100003096 97 avenue Denfert Rochereau SO-NE 0 2019-08-01T01:00:00Z 2012-02-22
2 100003096-SC 97 avenue Denfert Rochereau SO-NE 100003096 97 avenue Denfert Rochereau SO-NE 0 2019-08-01T04:00:00Z 2012-02-22
Les 10 principales stations à l'issue de la question 2
Comptage horaire
Nom du compteur
26 boulevard de Ménilmontant SE-NO 109.462847
35 boulevard de Menilmontant NO-SE 117.180643
21 boulevard Saint Michel S-N 117.730884
67 boulevard Voltaire SE-NO 119.208018
72 boulevard Voltaire NO-SE 124.391365
Figure 1 sans travail sur le style:

Figure 2 sans travail sur le style:

On commence à avoir quelque chose qui commence à transmettre un message synthétique sur la nature des données. On peut néanmoins remarquer plusieurs éléments problématiques (par exemple les labels) mais aussi des éléments ne correspondant pas (les titres des axes, etc.) ou manquants (le nom du graphique…).

Comme les graphiques produits par Pandas suivent la logique très flexible de matplotlib, il est possible de les customiser. Cependant, c’est souvent beaucoup de travail et la grammaire matplotlib n’est pas aussi normalisée que celle de ggplot en R. Il peut être préférable de directement utiliser seaborn, qui offre quelques arguments prêts à l’emploi.

Utiliser directement seaborn

Vous pouvez repartir des deux dataframes précédents. On va supposer qu’ils se nomment df1 et df2.

La figure comporte maintenant un message mais il est encore peu lisible. Il y a plusieurs manières de faire un barplot en seaborn. Les deux principales sont :

  • sns.catplot ;
  • sns.barplot.

On propose d’utiliser sns.catplot pour cet exercice.

A l’issue de la question 2, c’est-à-dire en utilisant seaborn pour reproduire de manière minimale un barplot, on obtient :

Après quelques réglages esthétiques, à l’issue des questions 3 et 4, on obtient une figure proche de celle de l’open data parisien.

On comprend ainsi que le boulevard de Sébastopol est le plus emprunté, ce qui ne vous suprendra pas si vous faites du vélo à Paris. Néanmoins, si vous n’êtes pas familiers avec la géographie parisienne, cela sera peu informatif pour vous, vous allez avoir besoin d’une représentation graphique supplémentaire: une carte ! Nous verrons ceci lors d’un prochain chapitre.

Les diagrammes en batons (barplot) sont extrêmement communs mais qu’ils transmettent. Sur le plan sémiologique, les lollipop charts sont préférables : ils transmettent la même information mais avec moins de bruit (la largeur des barres du barplot noie un peu l’information).

Text(0, 0.5, 'La somme des vélos comptabilisés sur la période sélectionnée')

Premières agrégations temporelles

On va maintenant se concentrer sur la dimension spatiale de notre jeu de données à travers deux approches :

  • Un diagramme en barre synthétisant l’information de notre jeu de données de manière mensuelle ;
  • Des séries instructives sur la dynamique temporelle. Cela sera l’objet de la prochaine partie.

Pour commencer, reproduisons la troisième figure qui est, encore une fois, un barplot. La première question implique une première rencontre avec une donnée temporelle à travers une opération assez classique en séries temporelles : changer le format d’une date pour pouvoir faire une agrégation à un pas de temps plus large.

month value
0 2019-08 33.637536
1 2019-09 55.831038

<Figure Size: (640 x 480)>

Si vous préférez représenter cela sous forme de lollipop1:

<Figure Size: (640 x 480)>

Première série temporelle

Il est plus commun de représenter sous forme de série les données ayant une dimension temporelle.

/opt/mamba/lib/python3.9/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead
/opt/mamba/lib/python3.9/site-packages/seaborn/_oldcore.py:1498: FutureWarning: is_categorical_dtype is deprecated and will be removed in a future version. Use isinstance(dtype, CategoricalDtype) instead
/opt/mamba/lib/python3.9/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.
/opt/mamba/lib/python3.9/site-packages/seaborn/_oldcore.py:1119: FutureWarning: use_inf_as_na option is deprecated and will be removed in a future version. Convert inf values to NaN before operating instead.
<matplotlib.collections.PolyCollection at 0x7f5c240faf70>

Des graphiques dynamiques avec Plotly

Contexte

L’inconvénient des figures avec ggplot est que celles-ci ne permettent pas d’interaction avec le lecteur. Toute l’information doit donc être contenue dans la figure ce qui peut la rendre difficile à lire. Si la figure est bien faite, avec différents niveaux d’information, cela peut bien fonctionner.

Il est néanmoins plus simple, grâce aux technologies web, de proposer des visualisations à plusieurs niveaux. Un premier niveau d’information, celui du coup d’oeil, peut suffire à assimiler les principaux messages de la visualisation. Ensuite, un comportement plus volontaire de recherche d’information secondaire peut permettre d’en savoir plus. Les visualisations réactives, qui sont maintenant la norme dans le monde de la dataviz, permettent ce type d’approche : le lecteur d’une visualisation peut passer sa souris à la recherche d’information complémentaire (par exemple les valeurs exactes) ou cliquer pour faire apparaître des informations complémentaires sur la visualisation ou autour.

Ces visualisations reposent sur le même triptyque que l’ensemble de l’écosystème web : HTML, CSS et JavaScript. Les utilisateurs de Python ne vont jamais manipuler directement ces langages, qui demandent une certaine expertise, mais vont utiliser des librairies au niveau de R qui génèreront automatiquement tout le code HTML, CSS et JavaScript permettant de créer la figure.

La librairie Plotly

Le package Plotly est une surcouche à la librairie Javascript Plotly.js qui permet de créer et manipuler des objets graphiques de manière très flexible afin de produire des objets réactifs sans avoir à recourir à Javascript.

Le point d’entrée recommandé est le module plotly.express (documentation ici) qui offre une arborescence riche mais néanmoins intuitive pour construire des graphiques (objets plotly.graph_objects.Figure) pouvant être modifiés a posteriori si besoin (par exemple pour customiser les axes).

Réplication de l’exemple précédent avec Plotly

Les représentations figées comme celles ci-dessus sont approriées pour des rapports ou articles. Néanmoins

Les modules suivants seront nécessaires pour construire des graphiques avec plotly:

La première question permet de construire le graphique suivant :

Alors qu’avec le thème sombre (question 2), on obtient :

Cette représentation montre bien le caractère spécial de l’année 2020. Pour rappeller au lecteur distrait la nature particulière de la période, marquée par un premier confinement qu’on voit bien dans les données, on pourrait, avec l’aide de la documentation, ajouter deux barres verticales pour marquer les dates de début et de fin de cette période.

Bonus

En bonus, l’état d’esprit des habitués de ggplot2 quand ils découvrent plotnine:

Back to top

Footnotes

  1. J’ai retiré la couleur sur l’axe des ordonnées qui, je trouve, apporte peu à la figure voire dégrade la compréhension du message.↩︎

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.