Seaborn est une bibliothèque construite au dessus Matplotlib. Elle améliore le rendu graphique par défaut de Matplotlib et offre des graphiques statistiques. Il est souvent plus simple d'essayer de faire sa figure directement sous Seaborn et si le rendu n'est pas satisfaisant ou qu'on ne peut pas faire ce qu'on désire, alors on utilise Matplotlib.
Seaborn est prévu pour fonctionner avec Pandas mais on peut l'utiliser sans Pandas.
Références¶
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
sns.__version__
'0.13.2'
Rendu graphique¶
Une des forces de Seaborn est de faire de jolis dessins et d'offrir différents styles. On pourra regarder https://seaborn.pydata.org/tutorial/aesthetics.html pour plus de détail.
sns.set_style('whitegrid') # background
sns.set_context("notebook") # change size of font, can be: paper (default), notebook, talk, poster
Des données pour faire de beaux graphiques¶
On va travailler avec la liste des maires de France élus en 2014.
import pandas as pd
import datetime as dt
import numpy as np
mayors = pd.read_excel("data/maires-2014.xlsx")
mayors.head()
Unnamed: 0 | Code du département (Maire) | Libellé de département (Maires) | Code Insee de la commune | Libellé de la commune | Population de la commune | Nom de l'élu | Prénom de l'élu | Genre | Date de naissance | Code profession | Libellé de la profession | Age | Type profession | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 1 | AIN | 1 | L'Abergement-Clémenciat | 780 | BOULON | Daniel | M | 1951-03-04 | 61 | Retraités salariés privés | 67.482612 | retraité |
1 | 1 | 1 | AIN | 2 | L'Abergement-de-Varey | 234 | ORSET | Max | M | 1947-11-02 | 65 | Autres retraités | 70.817383 | retraité |
2 | 2 | 1 | AIN | 4 | Ambérieu-en-Bugey | 13839 | FABRE | Daniel | M | 1961-09-07 | 51 | Cadres (entreprises publiques) | 56.969050 | entrep. publique |
3 | 3 | 1 | AIN | 5 | Ambérieux-en-Dombes | 1600 | PERNET | Pierre | M | 1961-07-29 | 42 | Professeurs du secondaire et techn. | 57.078566 | enseignement |
4 | 4 | 1 | AIN | 6 | Ambléon | 112 | BIONDA | Annie | F | 1951-11-28 | 63 | Retraités fonct.publique (sf enseig.) | 66.746115 | retraité |
mayors.Genre.value_counts()
Genre M 30171 F 5715 Name: count, dtype: int64
Présentation des données¶
Relation plot relplot
permet de présenter les données
suivant un nuage de points ou une courbe :
- sous forme de points avec l'argument
kind = "scatter"
ou plus directement avecscatterplot
(valeur par défaut) - sous forme de courbe avec l'argument
kind = "line"
ou plus directement aveclineplot
Une simple courbe¶
Comme indiqué initialement, Seaborn fonctionne bien avec Pandas mais pour commencer regardons comment afficher une simple
courbe avec des valeurs pour x et d'autres pour y. On va trier les communes par leur population et afficher les tailles dans l'ordre afin de voir la répartition des communes suivant leur taille. Pour cela on est obligé d'utiliser lineplot
car
relplot
demande un DataFrame.
ax = sns.lineplot(x=np.arange(len(mayors)), y=np.sort(mayors['Population de la commune']))
ax.set_title('Taille des %d communes' % len(mayors))
ax.set(yscale='log') # you can try without a logarithm scale in y to see the result
[None]
On note qu'il y a plus de communes en dessous de 100 habitants qu'au dessus de 10 000 habitants.
Distribution des données¶
On peut vouloir regarder la corrélation entre deux champs. Ainsi les maires ont un âge et leur ville a un nombre d'habitant ce qui permet d'afficher l'âge en fonction de la taille de la population (pour voir si plus une ville est grande, plus son maire est âgé par exemple).
g = sns.relplot(data=mayors, x='Age', y='Population de la commune')
g.set(yscale='log') # same, without the log scale we cannot see anything
<seaborn.axisgrid.FacetGrid at 0x7f043e2d2450>
On peut aussi utiliser la couleur pour indiquer un troisième champs (argument hue
) qui peut être une valeur réelle ou pas. La profession du maire ou son sexe par exemple sont des catégories et non des valeurs réelles mais cela convient.
On peut avoir un quatrième champs (argument col
) mais alors il doit être une catégorie puisqu'on dessinera une figure par valeur.
sns.set_style('dark')
sns.set_context("talk")
color_profession = {'agriculture':'g','industrie/commerce':'brown', 'privé':'cyan', 'libéral':'b', 'divers':'pink',
'fonctionnaire':'yellow', 'enseignement':'orange', 'entrep. publique':'r', 'retraité':'black'}
g = sns.relplot(data=mayors, x='Age', y='Population de la commune', hue='Type profession', palette=color_profession,
marker='.', col='Genre')
g.set(yscale='log')
<seaborn.axisgrid.FacetGrid at 0x7f043ee93610>
sns.set_style('white')
sns.set_context("notebook")
g = sns.relplot(data=mayors, x='Age', y='Population de la commune', hue='Genre', col='Type profession', col_wrap=3)
g.set(yscale='log', xlim=(20,100), ylim=(1,3000000))
<seaborn.axisgrid.FacetGrid at 0x7f043e301a90>
Corrélation globale de N champs 2 à 2¶
pairplot
offre une vision globale des corrélations entre tous les champs d'un jeu de données. Il affiche une matrice NxN de figures
(avec N le nombre de champs pris en compte) avec pour la répartition d'un champs par rapport à un autre et sur la
diagonale l'histogramme du champs concerné.
Il est possible d'avoir un champs qui définie la couleur avec l'argument hue
. Ce champs n'est pas pris en compte dans le nombre N de la matrice.
sns.set_style('darkgrid')
mayors['Taille commune'] = np.log10(mayors['Population de la commune'])
sns.pairplot(data=mayors[mayors['Type profession']=='fonctionnaire'][['Age', 'Taille commune', 'Genre']],
markers='+', hue='Genre', aspect=2)
<seaborn.axisgrid.PairGrid at 0x7f043d5fd190>
Afficher les valeurs de différentes catégories¶
catplot
permet de comparer toutes les catégories d'un
champs par rapport à un champs réel. Le type d'affichage est défini par l'argument kind
. On a :
point
qui affiche la moyenne et l'écart type pour chaque catégorie et les relie avec des lignes (utile si les catégories sont ordonnées et qu'on veut suivre l'évolution, des années par exemple)bar
qui affiche la même chose quepoint
mais avec des bares et sans relier les catégories (intérêt pas évident)box
etboxen
offrent un affichage statistique de chaque catégorie (meilleure représentation statistique AMHA)swarm
affiche un point par élément dans en forme d'arbre (bien pour voir le nombre d'éléments de chaque catégorie)strip
affiche un point par élément dans une sorte de colonne (bien pour voir le nombre d'éléments maisswarm
est plus joli AMHA)violin
intègre dans une courbe les éléments de chaque catégorie pour en faire une pyramide ou un violon (affichage parfait pour une pyramide des âges ou équivalent)
Regarder l'âge des maires pour chaque type de profession revient à dessiner des pyramides des âges en séparant les femmes des hommes. La pyramide se fait avec kind = 'violin'
.
sns.set_style('whitegrid')
g = sns.catplot(data=mayors, x='Type profession', y="Age", hue="Genre", palette="muted",
kind='violin', scale='count', split=True, aspect=3)
g.set(title="Pyramide des âges des maires pour chaque famille de profession") # Mayors' age-sex pyramid for each type of professions
g.set_xticklabels(rotation=30, ha='right')
/tmp/ipykernel_627/366515780.py:1: FutureWarning: The `scale` parameter has been renamed and will be removed in v0.15.0. Pass `density_norm='count'` for the same effect. g = sns.catplot(data=mayors, x='Type profession', y="Age", hue="Genre", palette="muted",
<seaborn.axisgrid.FacetGrid at 0x7f043e222810>
La catégorie "divers" a le plus de femmes. Regardons en détail les différents métiers de cette catégorie et affichons un point par maire avec kind = 'swarm'
:
g = sns.catplot(data=mayors[mayors['Type profession']=='divers'], x='Code profession', y="Age", hue="Genre",
kind='swarm', aspect=3)
avec pour le Code profession :
- 54 : permanent politique
- 55 : ministre du culte (il n'y en a pas)
- 56 : autres professions
- 57 : sans profession déclarée
Les femmes sont majoritaire dans la profession "sans profession"...
Courbe de niveaux¶
Lorsqu'on a trop de données, afficher des petits points les uns sur les autres devient vite illisible.
joinplot
offre une alternative intéressante qui
permet d'estimer le nombre d'instances qui partagent les mêmes valeurs.
Pour cela il affiche un histogramme suivant chaque axe et, si kind='kde'
, une carte sous forme de relief.
Le sommet de la montagne représente le plus grand nombre de maires qui partage le même âge et un ville de même taille. Dans notre cas, il s'agit des maires de 70 ans dans des villes de 300 habitants.
sns.set_style('white')
sns.jointplot(x=mayors.Age, y=np.log10(mayors['Population de la commune']), kind='kde',
height=8, xlim=((20,100)), ylim=np.log10((1,3000000)))
<seaborn.axisgrid.JointGrid at 0x7f042f632450>
Malheureusement joinplot
ne permet pas d'avoir la légende qui indiquerait la valeur des lignes de niveaux...
On peut en avoir une idée affichant l'histogramme des âges. Le maximum est à 70 ans avec presque 5 % des maires qui ont cet âge.
sns.set_style('whitegrid')
plt.figure(figsize=(10, 5))
sns.distplot(mayors.Age, bins=33)
/tmp/ipykernel_627/2318274114.py:3: UserWarning: `distplot` is a deprecated function and will be removed in seaborn v0.14.0. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms). For a guide to updating your code to use the new functions, please see https://gist.github.com/mwaskom/de44147ed2974457ad6372750bbe5751 sns.distplot(mayors.Age, bins=33)
<Axes: xlabel='Age', ylabel='Density'>
len(mayors[(mayors.Age > 69.5) & (mayors.Age < 70.5)]) / len(mayors)
0.04851474112467257
plt.figure(figsize=(10, 6))
ax =sns.regplot(data=mayors[mayors.Genre=='M'], x='Age', y='Population de la commune', color='b', marker='.', order=3)
sns.regplot(data=mayors[mayors.Genre=='F'], x='Age', y='Population de la commune', color='orange', marker='.', order=3)
ax.set(yscale='log', xlim=(20,100), ylim=(1,3000000))
[None, (20.0, 100.0), (1, 3000000)]
On a vu que les femmes sont 5 fois moins nombreuses, on voit qu'elles gèrent des villes plus petites sauf autour de 60 ans où elles dépassent les hommes (effet Hidalgo ?).
On note aussi la zone d'incertude qui est tellement large pour les femmes de moins de 38 ans et de plus de 77 ans que la courbe n'a rapidement plus beaucoup de sens.
Moyenne et quartiles¶
Enfin l'affichage de boîtes à moustache donne
- la moyenne au milieu de la boite
- le premier et dernier quartile forment la boite
- la plus grande et plus petite valeur prises en compte sont les extrèmités de traits verticaux
- les points (losanges) en dehors des traits verticaux sont les données aberrantes donc pas prises en compte
g = sns.catplot(data=mayors, x='Type profession', y="Age", hue="Genre", palette="muted",
kind='box', aspect=3)
g.set(title="Quartiles des âges des maires pour chaque famille de profession") # Mayors' age-sex pyramid for each type of professions
g.set_xticklabels(rotation=30, ha='right')
<seaborn.axisgrid.FacetGrid at 0x7f043d5e8a50>
Plus¶
Je vous invite à regarder la gallerie d'exemples pour avoir d'autres exemples des possibilités de Seaborn.