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¶

  • liste des fonctions
  • gallerie d'exemples
In [1]:
import matplotlib.pyplot as plt
import seaborn as sns

%matplotlib inline
%config InlineBackend.figure_format = 'retina'

sns.__version__
Out[1]:
'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.

In [2]:
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.

In [3]:
import pandas as pd
import datetime as dt
import numpy as np

mayors = pd.read_excel("data/maires-2014.xlsx")
In [4]:
mayors.head()
Out[4]:
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é
In [5]:
mayors.Genre.value_counts()
Out[5]:
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 avec scatterplot (valeur par défaut)
  • sous forme de courbe avec l'argument kind = "line" ou plus directement avec lineplot

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.

In [6]:
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
Out[6]:
[None]
No description has been provided for this image

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).

In [7]:
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
Out[7]:
<seaborn.axisgrid.FacetGrid at 0x7f043e2d2450>
No description has been provided for this image

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.

In [8]:
sns.set_style('dark')
sns.set_context("talk")
In [9]:
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')
Out[9]:
<seaborn.axisgrid.FacetGrid at 0x7f043ee93610>
No description has been provided for this image
In [10]:
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))
Out[10]:
<seaborn.axisgrid.FacetGrid at 0x7f043e301a90>
No description has been provided for this image

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.

In [11]:
sns.set_style('darkgrid')
In [12]:
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)
Out[12]:
<seaborn.axisgrid.PairGrid at 0x7f043d5fd190>
No description has been provided for this image

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 que point mais avec des bares et sans relier les catégories (intérêt pas évident)
  • box et boxen 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 mais swarm 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'.

In [13]:
sns.set_style('whitegrid')
In [14]:
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",
Out[14]:
<seaborn.axisgrid.FacetGrid at 0x7f043e222810>
No description has been provided for this image

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' :

In [15]:
g = sns.catplot(data=mayors[mayors['Type profession']=='divers'], x='Code profession', y="Age", hue="Genre", 
                kind='swarm', aspect=3)
No description has been provided for this image

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.

In [16]:
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)))
Out[16]:
<seaborn.axisgrid.JointGrid at 0x7f042f632450>
No description has been provided for this image

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.

In [17]:
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)
Out[17]:
<Axes: xlabel='Age', ylabel='Density'>
No description has been provided for this image
In [18]:
len(mayors[(mayors.Age > 69.5) & (mayors.Age < 70.5)]) / len(mayors)
Out[18]:
0.04851474112467257

Statistiques¶

regplot permet de tracer des régressions.

In [19]:
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))
Out[19]:
[None, (20.0, 100.0), (1, 3000000)]
No description has been provided for this image

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
In [20]:
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')
Out[20]:
<seaborn.axisgrid.FacetGrid at 0x7f043d5e8a50>
No description has been provided for this image

Plus¶

Je vous invite à regarder la gallerie d'exemples pour avoir d'autres exemples des possibilités de Seaborn.

In [ ]: