Chapitre 2 : Visualiser les données
Ce tutoriel vise à explorer différents packages de visualisation sous python se différenciant notamment sur la niveau de facilité pour réaliser, personnaliser et formater les graphiques, sur la diversité des graphiques réalisables et sur le choix entre visualisation statique et visualisation interactive. Sans prétention d’exhaustivité, notre exploration se retreint essentiellement à cinq librairies incontournables :
- la librairie historique de visualisation : matplotlib
- une surcouche de matplotlib : seaborn
- une librairie avec une syntaxe proche de R : plotnine
- un outil de visualisations interactives : plotly (ou de façon alternative cufflinks)
- une librairie de visualisations Web interactives : bokeh
Il pourrait aussi être intéressant de jeter un oeil à la libraire altair qui semble proposer une très large palette de belles visualisations. Dans ce tutoriel, on n’abordera ni les librairies pydot qui permet essentiellement la génération de graphes, ni la libraire networkX qui est très largement axée sur l’analyse des graphes et des réseaux.
Quoi représenter ? Comment choisir le type de graphique adéquat ?
Afin d’explorer ces différentes librairies, nous utiliserons un jeu de données restreints que vous allez contruire ! De plus, a minima, un graphique (dont un graphique commun représentant les 10 villes avec le patrimoine moyen le plus élevé parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF) sera réalisé avec chacune des librairies afin de faciliter leur comparaison.
Exercice 1 : A partir des données Excel sur l’impôt sur la fortune (isfcom2017.xlsx), construire deux dataframes : le premier patrimoine_top qui contient les 10 villes avec le patrimoine moyen le plus élevé et le second impot_top qui regroupe les 10 villes avec les redevables de l’isf payant en moyenne le plus d’impôt (parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF).
isf=pd.read_excel("isfcom2017.xlsx", sheet_name="définitif_patrimoine", header=1)
print(isf.shape)
isf.head(2)
# On fusionne avec la table commune pour récupérer le libellé des communes
import re
communes=pd.read_csv("commune2019.csv")
isf["codeCommune"]=[re.sub(' ','', str(x)) for x in isf["Code commune (INSEE)"]]
isf=pd.merge(communes, isf, left_on="com", right_on="codeCommune", how='inner')
isf=isf[isf.typecom!='COMD']
patrimoine_top=isf.sort_values('patrimoine moyen en €', ascending=False).head(10)
impot_top=isf.sort_values('impôt moyen en €', ascending=False).head(10)
La librairie historique de visualisation : matplotlib
Quelques mots sur la syntaxe :
- Chargement de la librarie : import matplotlib.pyplot as plt
- Création d’une figure vide en fixant des paramètres comme la taille de l’image fig = plt.figure(figsize=(10,4)) [Etape optionnelle]
- Alternative pour diviser la fenêtre graphique en sous-fenêtres avec deux graphiques l’un en dessous de l’autre : f, (ax1, ax2) = plt.subplots(nrows=2,ncols=1, figsize=(15, 10)) [Etape optionnelle]
- Tracé du graphique avec la commande plt.nomGraphique (par exemple, plt.plot pour un tracé linéaire, plt.scatter pour nuage de points, plt.bar pour un graphique à barres …)
- Ajout de paramètres (titres aevc *plt.title ou ax.set_title, label de l’axe des abscisses plt.xlabel ou ax.set_xlabel, …) [Etape optionnelle]
Pour réaliser un graphique, référez-vous à la documentation officielle. Le site détaille aussi la syntaxe et les options pour réaliser de nombreux types de graphiques avec matplotlib. Si vous avez besoin d’un aide mémoire, consultez le cheat sheet !
Exercice 1 : Tracer le diagramme à barres horizontales représentant les 10 villes avec le patrimoine moyen le plus élevé parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF.
fig = plt.figure(figsize=(10,4))
plt.barh(patrimoine_top['libelle'], patrimoine_top['patrimoine moyen en €'], align='center', color='blue', height=0.7)
plt.xlabel('patrimoine moyen en €')
plt.title('Quelles communes abritent les plus hauts patrimoines ?')
Exercice 2 : Tracer les deux diagrammes à barres horizontales représentant respectivement les 10 villes avec le patrimoine moyen le plus élevé et les 10 villes avec les redevables de l’isf payant en moyenne le plus d’impôt parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF.
f, (ax1, ax2) = plt.subplots(nrows=2,ncols=1, figsize=(15, 10))
ax1.barh(patrimoine_top['libelle'], patrimoine_top['patrimoine moyen en €'], align='center', color='blue',height=0.7)
ax1.set_xlabel('patrimoine moyen en €')
ax1.set_title('Quelles communes abritent les plus hauts patrimoines ?')
ax2.barh(impot_top['libelle'], impot_top['impôt moyen en €'], align='center', color='magenta',height=0.7)
ax2.set_xlabel('impôt moyen en €')
ax2.set_title("Quelles communes abitrent les redevables de l'isf payant le plus d'impôt en moyenne ?")
Votre graphe ne s’affiche pas dans votre notebook mais aucune erreur ne se produit ? Assurez-vous que la ligne de code suivante est bien ajoutée dans votre notebook :
%matplotlib inline
Toutefois, pour avoir un environnement interactif, il peut être préférable d’utiliser la commande suivante :
%matplotlib notebook
Il est possible de directement réaliser des graphes à partir d’un dataframe pandas. Pour cela, on peut s’appuyer sur la documentation de pandas.
Exercice : Directement à partir du dataframe * patrimoine_top*, tracer le diagramme à barres horizontales représentant les 10 villes avec le patrimoine moyen le plus élevé parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF.
patrimoine_top.plot(kind='barh', y='patrimoine moyen en €', x='Commune', figsize=(10,5), facecolor="magenta",
legend=False, title='Quelles communes abritent les plus hauts patrimoines ?', subplots=1)
Une surcouche de *matplotlib* : seaborn
Une documentation officielle peut, comme pour matplotlib, être complétée par le site. Comme pour matplotlib, n’hésitez pas à consulter le cheat sheet de Seaborn.
-
Les plus de Seaborn
- Faciliter la visualisation
- Rendre la visualisation plus attrayante avec notamment une palette de couleur spécifique
-
Un inconvénient principal : Un nombre plus restreint de visualisations possibles dont les principales sont :
Fonction | Résultat | |
---|---|---|
Analyse des variables quantitatives | sns.scatterplot() ou sns.replot(kind="scatter") | Tracé du nuage de points |
sns.lineplot() ou sns.replot(kind="line") | Tracé linéaire entre les points | |
Analyse des variables catégorielles | sns.boxplot() | Représentation d'un diagramme en boîte mettant en exergue les quantiles de la distribution et les points extrêmes |
sns.violinplot() | Représentation de la courbe de densité de probabilité des différentes valeurs et de la distribution des données | |
sns.barplot() | Graphique à barres de longueur proportionnelle à la valeur représentée | |
sns.countplot() | Graphique représentant le nombre d'observations associées à une variable donnée | |
Analyse de la distribution des données | sns.distplot() | Distribution / histogramme avec ou sans représentation de la densité estimée (Kernel Density Estmation - KDE) |
Exercice 1 : A partir de seaborn, tracer le diagramme à barres horizontales représentant les 10 villes avec le patrimoine moyen le plus élevé parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF.
import seaborn as sns
fig = plt.figure(figsize=(10,4))
sns.set(style="whitegrid")
bar_plot = sns.barplot(y=patrimoine_top["Commune"],x=patrimoine_top["patrimoine moyen en €"],
palette=sns.color_palette("Blues_d"), errwidth =False)
plt.xticks(rotation=90)
plt.show()
Exercice 2 : A partir de la table isf, tracé le diagramme à barres verticales représentant les nombre de communes parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF.
fig = plt.figure(figsize=(20,4))
sns.set(style="whitegrid")
sns.countplot(x="Région", data=isf)
plt.xticks(rotation=90)
Exercice 3 : A partir de la table isf, représenter l’impôt moyen selon le patrimoine moyen (pour les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF).
fig = plt.figure(figsize=(8,5))
sns.set(style="white")
sns.scatterplot(x="patrimoine moyen en €", y='impôt moyen en €', data=isf)
Une librairie avec une syntaxe proche de R : plotnine
Si la librairie ggplot propose dès 2014 une version partielle de ggplot sous python avec l’ambition de respecter le concept de Grammar of Graphics, cette librairie n’est toutefois plus maintenue depuis 2016. Son installation pose d’ailleurs des problèmes de compatibilité avec la version actuelle de pandas. La librairie plotnine, toujours en cours de développement, constitue une alternative intéressante pour les aficionados de R souhaitant utiliser python !
IL n’est pas forcément utile de réaliser un grand nombre d’exemples notamment en raison de sa grande similarité avec la syntaxe de R, testons la simplement en réalisant le même diagramme que pour les autre librairies.
Exercice : A partir de plotnine, tracer le diagramme à barres horizontales représentant les 10 villes avec le patrimoine moyen le plus élevé parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF.
!pip install plotnine
import plotnine
# Pour ordonner les labels par ordre croissant de patrimoine moyen
commune_cat=pd.api.types.CategoricalDtype(patrimoine_top.libelle.tolist(), ordered=True)
patrimoine_top['commune_cat'] = patrimoine_top['libelle'].astype(str).astype(commune_cat)
p = plotnine.ggplot(patrimoine_top , aes( x = patrimoine_top["commune_cat"], y = "patrimoine moyen en €")) + \
geom_bar(stat='identity', fill='magenta') + \
ggtitle("Quelles communes abritent les plus hauts patrimoines ?" ) + \
ylab("patrimoine moyen en €" ) + \
xlab("Commune") + \
coord_flip() + \
theme(axis_text_x = element_text( angle = 0 )) + \
theme(panel_background=element_rect(fill='white'),
axis_line_x=element_line(color='black'),
axis_line_y=element_line(color='black'))
print(p)
Un outil de visualisations interactives : plotly
Comme pour les autres librairies, la documentation officielle de plotly est riche : elle présente la syntaxe relative à chaque fonction, notamment à travers une large palette d’exemples. Pour la syntaxe globale, n’hésitez pas aussi à consulter le cheat sheet !
-
Les plus de plotly :
- Création de visualisations interactives construites à l’aide de D3.js (sans même connaître D3.js !)
- En dehors de python, plotly peut être utilisé sans connaissances techniques pour créer des tracés interactifs, via l’interface graphique de plotly
- Visualisations partageables en ligne avec plusieurs personnes
- Intégration possible des graphiques interactifs dans des projets ou des sites Web
-
L’inconvénient principal :
- L’utilisation de l’interface graphique de plotly oblige l’utilisateur à rendre ses données publiques qui sont alors consultables par tous.
Comme l’indique la documentation, plotly permet aussi de créer hors ligne :
- avec plotly.offline.plot() pour créer et sauvegarder le graphique en html et l’afficher dans le navigateur
- avec plotly.offline.iplot() pour créer et afficher le graphique au sein d’un jupyter notebook
Exercice 1 : A partir de plotly, tracer le diagramme à barres horizontales représentant les 10 villes avec le patrimoine moyen le plus élevé parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF.
import plotly.graph_objs as go
# Ensemble des données pour la visualisation
data = [
go.Bar(x=patrimoine_top['patrimoine moyen en €'],
y=patrimoine_top['Commune'], orientation = 'h',
marker=dict(color='magenta'))
]
# Apparence du graphique
layout = go.Layout(
title='Quelles communes abritent les plus hauts patrimoines ?',
font=go.layout.Font(
family='Arial', size=10
),
showlegend=False,
xaxis=dict(
showgrid=True,
showline=True,
showticklabels=True,
zeroline=True,
exponentformat='none'
),
yaxis=dict(
automargin= True
),
bargap=0.1
)
fig = go.Figure(data=data, layout=layout)
plotly.offline.iplot(fig) # Option filename si on souhaite sauvegarder la figure
Pour combiner de façon efficiente, il est possible d'utiliser la librairie **cufflinks** qui facilite la réalisation de graphiques avec *plotly* à partir de *dataframes pandas*. Quelques tutoriels sont disponibles sur leur github ou sur le site de plotly.
Exercice 2 : A partir de cufflinks, tracer le diagramme à barres horizontales représentant les 10 villes avec le patrimoine moyen le plus élevé parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF.
import cufflinks as cf
# Pour permettre un affichage au sein du notebook
cf.go_offline()
patrimoine_top[['libelle','patrimoine moyen en €']].iplot(kind='bar', y='patrimoine moyen en €', x='libelle',
xTitle='patrimoine moyen en €', yTitle='Commune',
barmode='group', orientation='h',
title='Quelles communes abritent les plus hauts patrimoines ?',
colors='magenta', bargap=0.2, margin=(200,50,50,50))
Exercice 3 : Comment contrôler l’apparence du graphique (par exemple la taille de la figure) si les paramètres n’existent pas dans la fonction iplot de cufflinks ? Tracer le diagramme précédent en fixant la taille de la figure.
import cufflinks as cf
# Pour permettre un affichage au sein du notebook
cf.go_offline()
Afin de modifier plus finement l’apparence du graphique, il est possible d’ajouter ces caractéristiques de mise en forme en paramètre de layout.
layout_cufflinks = cf.Layout(
height=500,
width=1000,
title='Quelles communes abritent les plus hauts patrimoines ?',
font=cf.layout.Font(
family='Arial', size=10
),
showlegend=False,
xaxis=dict(
showgrid=True,
showline=True,
showticklabels=True,
zeroline=True,
exponentformat='none'
),
yaxis=dict(
automargin= True
),
bargap=0.1
)
patrimoine_top[['libelle','patrimoine moyen en €']].iplot(kind='bar', y='patrimoine moyen en €', x='libelle',
xTitle='patrimoine moyen en €', yTitle='Commune',
barmode='group', orientation='h',
title='Quelles communes abritent les plus hauts patrimoines ?',
colors='magenta', bargap=0.2, margin=(800,50,50,50),
layout=layout_cufflinks.to_plotly_json())
Une librairie de visualisations Web interactives : bokeh
Difficile de présenter plotly et d’ignorer complètement bokeh ! Pour faciliter la prise en main de bokeh, vous pouvez consulter la documentation officielle ou le cheat sheet. Bokeh présente toutefois quelques défauts indéniables :
- Moins d’exemples en ligne et documentation parfois insuffisante (essentiellement basée sur des exemples)
- Moins intégré avec pandas que plotly (bokeh s’intègre aux Pandas à l’aide de la ColumnDataSourceclasse, cette fonction est présente dans le module bokeh.models)
Exercice : A partir de bokeh, tracer le diagramme à barres horizontales représentant les 10 villes avec le patrimoine moyen le plus élevé parmi les villes de plus de 20 000 habitants ayant plus de 50 redevables à l’ISF.
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
output_notebook()
p = figure(plot_width=800, plot_height=400, y_range=patrimoine_top['libelle'].tolist(),
title="Quelles communes abritent les plus hauts patrimoines ?",)
p.hbar(y='libelle', right='patrimoine moyen en €', height=0.8, alpha=0.7, source=source, color="magenta")
show(p)