Visualisation

Lorsque j'aborde un document scientifique, la première chose que je fais après avoir lu le résumé est de regarder les graphiques. Un graphique bien conçu est dense en information, de sorte qu'il met en lumière une information qui pourrait passer inaperçue dans un tableau.

Vous reconnaîtrez peut-être ce graphique.

Source: [GIEC, Bilan 2001 des changements climatiques : Les éléments scientifiques](https://www.ipcc.ch/pdf/climate-changes-2001/scientific-basis/scientific-spm-ts-fr.pdf)

Ce graphique, conçu par Michael E. Mann, Raymond S. Bradley et Malcolm K. Hughes, montre l'évolution des températures en °C normalisées selon la température moyenne entre 1961 et 1990 sur l'axe des Y en fonction du temps, sur l'axe des X. On le connait aujourd'hui comme le bâton de hockey, et on reconnait son rôle clé pour sensibiliser la civilisation entière face au réchauffement global, et a repoussé dans la marge les courrants négateurs.

Les températures précédent le 20ième siècle ont été reconstruites à partir de données indirectes. Les auteurs du graphique ont pris soin d'indiquer l'incertitude de leurs reconstruction, qui devient de plus en plus étroites avec le temps.

On aura recours à la visualisation des données lorsque l'information d'un tableau devient difficile à interpréter. Ainsi, créer des graphiques est une tâche courrante dans un flux de travail en science, que ce soit pour explorer les données ou les communiquer, ce à quoi cette section est vouée.

Pourquoi explorer grapiquement?

Tout comme la création de sommaires (par exemple avec la méthode describe de pandas) vise d'abord à explorer des données, je parie que la majorité des graphiques que vous créerez ne seront pas voués à être publiés. Prenons deux variables quelconques, $X$ et $Y$. Vous calculez leur moyenne, écart-type et la corrélation entre les deux variables (nous verrons les statistiques en plus de détails dans le prochain chapitre). Je ne vous surprendrai pas en disant que ces statistiques sont insuffisantes pour bien apprécier ce que vous avez sous les yeux. Pour le démontrer, Matejka et Fitzmaurice (2017) ont généré 12 jeux de données $X$ et $Y$, ayant chacun pratiquement les mêmes statistiques. Mais avec des structures bien différentes.

Animation montrant la progression du jeu de onnées *Datasaurus* poir toutes les formes visées. Source: [Same Stats, Different Graphs: Generating Datasets with Varied Appearance and Identical Statistics through Simulated Annealing](https://www.autodeskresearch.com/publications/samestats).

Publier un graphique

Cinq qualités d'un bon graphique

Alberto Cairo, chercheur spécialisé en visualisation de données, a fait paraître en 2016 le livre The Truthful art, note cinq qualités d'une visualisation bien conçue (les citations de cette section proviennent de ma traduction de Alberto Cairo, The Truthful art (2016), p. 45.).

1- Elle est véritable, puisqu'elle est basée sur une recherche exhaustive et honnête.

Cela vaut autant pour les graphiques que pour l'analyse de données. Il s'agit froidement de présenter les données selon l'interprétation la plus exacte. Les pièges à éviter sont le picorage de cerises et la surinterprétation des données. Le picorage, c'est lorsqu'on réduit les perspectives afin de soutenir un argumentaire. Par exemple, retirer des données d'une région ou d'une décénie qui rendraient factice une conclusion fixée a priori. Ceci vaut autant pour les graphiques que pour les statistiques (nous parlerons du p-hacking au prochain chapitre). La surinterprétation, c'est lorsque l'on saute rapidement aux conclusions: par exemple, que l'on génère des corrélations, voire même des relations de causalités à partir de ce qui n'est que du bruit de fond.

2- Elle est fonctionnelle, puisqu'elle constitue une représentation précise des données, et qu'elle est construite de manière à laisser les observateurs.trices prendre des initiatives consquentes.

"La seule chose qui est pire qu'un diagramme en pointe de tarte, c'est d'en présenter plusieurs" (Edward Tufte, designer, cité par Alberto Cairo, 2016, p. 50). Choisir le bon graphique pour représenter vos données est beaucoup moins une question de bon goût qu'une question de démarche rationnelle sur l'objectif visé par la présentation d'un graphique. Je présenterai des lignes guides pour sélectionner le type de graphique qui présentera vos données de manière fonctionnelle en fonction de l'objectif d'un graphique (d'ailleurs, avez-vous vraiment besoin d'un graphique?).

3- Elle est attrayante et intrigante, et même esthétiquement plaisante pour l'audience visée - les scientifiques d'abord, mais aussi le public en général.

En sciences naturelles, la pensée rationnelle, la capacité à organiser la connaissance et créer de nouvelles avenues sont des qualités qui sont privilégiées au talent artistique. Que vous ayez où non des aptitudes en art visuel, présentez de l'information, pas des décorations. Excel vous permet d'ajouter une perspective 3D à un diagramme en barres. La profondeur contient-elle de l'information? Non. Cette décoration ne fait qu'ajouter de la confuusion. Minimalisez, fournissez le plus d'information possible avec le moins d'éléments possible. Si vous manquez d'idées, ouvrez un bon livre de référence en visualisation, comme le livre de Alberto Cairo (2016).

4- Elle est pertinente, puisqu'elle révèle des évidences scientifiques autrement difficilement acessibles.

Il s'agit de susciter un euréka, dans le sens qu'elle génère une idée, et parfois une initiative, en un coup d'oeil. Le graphique en bâton de hockey est un exemple où l'on a spontanément une idée de la situation. Cette situation peut être la présence d'un phénomène comme l'augmentation de la température globale, mais aussi l'absence de phénomène, par exemple l'absence d'augmentation du rendement d'une culture selon la dose de phosphore appliquée.

5- Elle est instructive, parce que si l'on saisit et accepte les évidences scientifiques qu'elle décrit, cela changera notre perception pour le mieux.

En présentant cette qualité, Alberto Cairo voulait insiter ses lecteurs.trices à choisir des sujets de discussion visuelle de manière à participer à un monde meilleur. En ce qui nous concerne, il s'agit de bien sélectionner l'information que l'on désire transmettre. Imaginez que vous avez travaillé quelques jours pour créer un graphique, sont vous êtes fier, mais vous (ou un collègue hiérarchiquement favorisé) vous rendez compte que le graphique soutient peu ou pas le propos de votre thèse/mémoire/rapport/article. Si c'est bien le cas, vous feriez mieux de laisser tomber votre oeuvre et considérer votre démarche comme une occasion d'apprentissage.

Alberto Cairo résume son livre The Truthful Art dans une entrevue avec le National Geographic.

Visualisation en Python

Les bibliothèques scientifique sur Python sont généralement bien organisées... sauf en ce qui a trait aux bibliothèques de visualisation. Jake Vanderplas, développeur de la bibliothèque altair, en dressait un portrait étourdissant.

[The Python Visualization Landscape](https://www.youtube.com/watch?v=FytuB8nFHPQ). Conférence de Jake Vanderplas, développeur de la bibliothèque altair, sur les outils de visualisation disponibles sur Python, PyCon 2017.

Il existe plusieurs outils pour créer des graphiques en Python, certains génériques, d'autres spécialisés, chacune ayant un fonctionnement qui lui est propre. Ces outils sont basés sur des approches que l'on pourrait placer sur un spectre allant de l'impératif au déclaratif.

Approche impérative

Selon cette approche, vous indiquez comment placer l'information dans un espace graphique. Vous indiquer les symboles, les couleurs, les types de ligne, etc. Peu de choses sont automatisées, ce qui laisse une grande flexibilité, mais demande de vouer beaucoup d'énergie à la manière de coder pour obtenir le graphique désiré.

Approche déclarative

Les stratégies d'automatisation graphique se sont grandement améliorées au cours des dernières années. Plutôt que de vouer vos énergies à créer un graphique, il est maintenant possible de spécifier ce que l'on veut présenter.

La visualisation déclarative vous permet de penser au données et à leurs relations, plutôt que des détails accessoires.

Jake Vanderplas, Declarative Statistical Visualization in Python with Altair LIEN (ma traduction)

Modules couverts

Il est difficile d'identifier les outils les plus pertinents pour les opérations courrantes en écologie mathématique. J'en suis arrivé à proposer les outils les plus établis dans l'univers Python.

  • Matplotlib est l'outil de base. Il fonctionne en mode impératif. Peu de choses sont générées automatiquement, mais ce que vous perdez en convivialité, vous le gagnez en flexibilité. Je ferai intervenir matplotlib le moins possible ce chapitre, mais plus souvent dans ce manuel pour des applications spécialisées. Nous utiliserons uniquement sont implémentation pyplot.
  • Seaborn utilise matplotlib en arrière plan pour créer des graphiques adaptés pour le travail en statistiques. Il n'est pas aussi intuitif qu'on pourrait le souhaiter, mais tent à utiliser un style déclaratif.

Autres modules

Ceci dit, les librairies suivantes peuvent aussi se révéler très utiles, et je les utiliserai à l'occasion.

  • Pandas ne se limite pas aux opérations sur les tableaux. C'est aussi un outil graphique, surtout exploratoire, qui est basé sur matplotlib.
  • plotnine. Les habitués du langage R connaissent probablement le module graphique ggplot2, qui reprend une grammaire graphique en mode purement déclaratif. plotnine est un clone de ggplot2 pour Python. Bien qu'il ne soit pas aussi complet, stable et mature que sa version pour R, la synthaxe est sensiblement la même. Si vous avez déjà appris ggplot2 et que vous désirez éviter de vous lancer dans un nouvel apprentissage de modules, plotnine formera une solution presque instantannée.
  • Altair. Module est tout neuf dans l'univers Python, conséquemment peu mature, Altair compte s'orienter vers la production de graphiques intéractifs déclaratifs pour des publications scientifiques. À surveiller.
  • Plotly. Bien que prétendument déclaratif, Plotly est plutôt un matplotlib pour créer des graphiques intéractifs, voire même des applications incluant des graphiques avec l'extension Dash, qu'il vaut la peine d'explorer si vous compter déployer votre code en logiciel. L'extension cufflinks permet d'accéder à une interface colnée sur la vizualisation avec pandas. Des fonctions en développement, mais suffisamment fonctionnelles sont placées dans la classe figure factory. On y retrouve une panoplie de fonctions pour les graphiques orientés statistique, notament en mode déclaratif. Plotly est développé à Montréal.
  • Bokeh. Il ressemble beaucoup à Plotly et à Dash, mais est orienté vers les données massives, en particulier en ce qui a trait à ses extensions Holoviews et Datashader. Il est développé par Anaconda.
  • Folium. Il est possible de créer des cartes avec Matplotlib, Geoplot, Plotly, Bokeh, etc. Mais Folium est conçu pour présenter des cartes interactives.

Choisir le type de graphique le plus approprié

Vous connaissez sans doute les nuages de point, les lignes, les histogrammes, les diagrammes en barre et en pointe de tarte. De nombreuses manières de présenter les données ont été développées. Les principaux types de graphique seront couverts dans ce chapitre. D'autres types spécialisés seront couverts dans les chapitres appropriés (graphiques davantage orientés vers les statistiques, les biplots, les dendrogrammes, les diagrammes ternaires, les cartes, etc.). Commme vous le verrez, la création d'un graphique demande d'abord d'organiser vos données: au lieu d'importer des donnnées déjà organisées, j'ai préféré présenter les démarches d'organisation menant aux données organisées de manière à créer le graphique visé.

Quoi qu'il en soit, selon Cairo (2016):

  1. Réfléchissez au message que vous désirez transmettre: comparer les catégories $A$ et $B$, visualiser une transition ou un changement de $A$ vers $B$, présenter une relation entre $A$ et $B$ ou la distribution de $A$ et $B$ sur une carte.

  2. Essayez différentes représentations: si le message que vous désirez transmettre a plusieurs volets, il se pourrait que vous ayaez besoin de plus d'un graphique.

  3. Mettez de l'ordre dans vos données. Le chapitre 3 visait à vous sensibilisé à l'importance d'avoir des données bien organisées, qui seront par la suite plus facile à visualiser.

  4. Testez le résultat. "Hé, qu'est-ce que tu comprends de cela?" Si la personne hausse les épaules, il va falloir réévaluer votre stratégie.

Il existe de nombreux bons sites pour assister dans le choix du bon graphique à utiliser. Je recommande en particulier datavizcatalogue.com. Les recommandations de Ann K. Emery sont aussi bien avisées. En ce qui a trait au "comment", des recettes sont proposées sur python-graph-gallery.com.

Le sujet étant vaste, cette section ne s'attardera pas à présenter les différents types de graphique, mais à présenter brièvement les modules graphiques de Python.

Matplotlib

Matplotlib est un module graphique fonctionnant sur Python, conçu pour fonctionner avec des listes, des matrices Numpy, et des tableaux Pandas. Matplotlib s'est imposé comme le générateur graphique de base sur Python. Bien que robuste, complet, stable et universel, Matplotlib n'est pas l'outil le plus facile à manier, ni le plus élégant visuellement (quoi que...). L'apparition de nouveaux outils graphiques plus domesticable et plus élégants (e.g. Altair, Plotly) pourraient nous amener à le considérer comme démodé. Matplotlib est néanmoins utilisé comme outil de base pour contruire des graphiques par Scipy, Seaborn, Pandas, Plotnine, etc.

Importer Matplotlib

Le diminutif plt est conventionnellement utilisé pour créer une instance du module matplotlib.pyplot. pyplot est une interface d'utilisation de Matplotlib basé sur l'approche de Matlab.


In [1]:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

Styliser Matplotlib

De nombreux styles ont été développés pour modifier le style par défaut de Matplotlib.


In [2]:
plt.style.available


Out[2]:
['dark_background',
 'seaborn-muted',
 'fivethirtyeight',
 'seaborn-poster',
 'classic',
 'seaborn',
 'seaborn-darkgrid',
 'seaborn-ticks',
 'Solarize_Light2',
 'seaborn-pastel',
 'seaborn-notebook',
 'seaborn-dark',
 'seaborn-bright',
 'seaborn-deep',
 'seaborn-talk',
 'seaborn-whitegrid',
 'seaborn-colorblind',
 'grayscale',
 'ggplot',
 '_classic_test',
 'seaborn-white',
 'bmh',
 'seaborn-paper',
 'fast',
 'seaborn-dark-palette']

Le style seaborn-dark-palette me semble visuellement plaisant.


In [3]:
plt.style.use('seaborn-dark-palette')

Matplotlib dans un notebook

À moins de travailler dans une console Python ou IPython, vous n'aurez pas besoin de lancer plt.show() dans un notebook pour afficher un graphique. Pour les graphiques soient affichés dans un notebook, la commande %matplotlib inline doit être préalablement lancée, peu importe si vous utilisez matplotlib, seaborn, pandas ou tout module graphique basé sur Matplotlib. La commande alterntive %matplotlib notebook peut être utilisée pour des graphiques plus intéractifs, mais en ce qui me concerne, le résultat n'est pas très convivial.


In [4]:
%matplotlib inline

Matplotlib: les principes

Disons que vous désiriez créer un graphique de la température et du point de rosée en fonction du temps. Le fichier weather_sherbrooke.csv contient ces variables pour la première semaine du mois d'août 2017 à Sherbrooke, QC.


In [5]:
sherb = pd.read_csv('data/weather_sherbrooke.csv', parse_dates=['time'])

Lançons le graphique avec plt.plot, qui est une fonction générique. Les commandes sont expliquées en commentaire.


In [6]:
plt.plot(sherb.time, sherb.temp) # température
plt.plot(sherb.time, sherb.temp_dew) # point de rosée
plt.xlabel('Time') # Titre de l'axe des x
plt.ylabel('Temperature / Dew point') # Titre de l'axe des y
plt.gcf().autofmt_xdate() # format automatique de date pour l'axe des x


Par défaut, plt.plot génère des lignes, et gère automatiquement les couleurs. Remarquez que l'axe des x est présenté en tant que secondes depuis le premier janvier 1900. Cela peut être corrigé, tout comme de nombreuses fonctions de personnalisation sont disponibles.

Mais pour l'instant, l'axe des y représente deux variables différentes, ce qui est loin d'être idéal pour la visualisation.

Les sous-graphiques

Pour créer des sous-graphiques, une manière conviviale est de travailler avec subplot. On inscrira plt.subplot(2, 1, 1) ou bien plt.subplot(211) pour indiquer un graphique à 2 lignes, 1 colonne, en activant le sous-graphique no 1 (l'indice est compté par ligne, de gauche à droite et à partir de 1).


In [7]:
plt.figure(figsize=[8, 4]) # dimension du graphique

plt.subplot(2, 1, 1) # (nombre de lignes, nombre de colonnes, et indice du sous-graphique à activer)
plt.plot(sherb.time, sherb.temp, color='green', linestyle=':', linewidth=2) # styles de ligne personnalisés
plt.ylabel('Temperature')

plt.subplot(2, 1, 2) # (2 lignes, 1 colonne, 2ième graphique), on aurait pu écrire plt.subplot(212)
plt.plot(sherb.time, sherb.temp_dew, color='magenta', linestyle='-.', linewidth=2)
plt.xlabel('Time')
plt.ylabel('Dew point')

plt.gcf().autofmt_xdate()
plt.tight_layout; # Pour éviter les superpositions d'axes
# Note: Terminer une cellule de graphique avec un ; permet d'éviter les sorties de texte


Matplotlib possède un interface de programmation à la Matlab, et un interface à la Python. L'interface à la Matlab est celui qui a été utilisé jusqu'à présent. En mode Matlab, les graphiques sont crées dans l'ordre d'exécution. Le mode Python, orientée objet, permet d'enchasser les élémnents dans des axes qui eux sont enchâssés dans des figures.


In [8]:
fig, ax = plt.subplots(2, 1)
ax[0].plot(sherb.time, sherb.temp)
ax[1].plot(sherb.time, sherb.temp_dew)
ax[0].set_title('Python interface')
ax[1].set_xlabel('Time')
ax[0].set_ylabel('Temperature')
ax[1].set_ylabel('Dew point')
ax[0].set_xticklabels('')
plt.gcf().autofmt_xdate()


Dans ce manuel, j'utiliserai l'interface qui me semblera approprié.

Limites sur les axes

Matplotlib gère automatiquement les limites des axes pour présenter toutes les données. Mais vous désirerez peut-être ne présenter qu'une partie de vos données.


In [9]:
import datetime # module pour gérer des dates

plt.plot(sherb.time, sherb.temp)
plt.xlabel('Time')
plt.ylabel('Temperature')
plt.xlim([datetime.date(2017, 8, 2), datetime.date(2017, 8, 3)]) # sous forme de liste [min, max] ou de tuple (min, max)
plt.ylim([10, 30])
plt.gcf().autofmt_xdate()


Légendes

Une légende permet d'associer une décoration graphique (forme / couleur) à une catégorie. Prenons par exemple des données de dimension de sépales de différentes variétés d'iris, données que l'on retrouve dans le module Seaborn, que nous couvrirons plus tard.


In [10]:
import seaborn as sns
iris = sns.load_dataset("iris")
iris.sample(3)


Out[10]:
sepal_length sepal_width petal_length petal_width species
29 4.7 3.2 1.6 0.2 setosa
93 5.0 2.3 3.3 1.0 versicolor
85 6.0 3.4 4.5 1.6 versicolor

In [11]:
plt.plot(iris.loc[iris.species == 'setosa', 'sepal_length'],
         iris.loc[iris.species == 'setosa', 'sepal_width'],
         'o', # seulement un point
         label='Setosa') # étiquette pour la légende
plt.plot(iris.loc[iris.species == 'versicolor', 'sepal_length'],
         iris.loc[iris.species == 'versicolor', 'sepal_width'],
        'o',
         label='Versicolor')
plt.plot(iris.loc[iris.species == 'virginica', 'sepal_length'],
         iris.loc[iris.species == 'virginica', 'sepal_width'],
        'o',
         label='Virginica')
plt.axis('equal') # les distances des unités en x et y sont égales
plt.xlabel('Sepal length (cm)')
plt.ylabel('Sepal width (cm)')
plt.legend(loc='lower right'); # afficher la légende, selon les labels, à la position donnée. 
                               # truc: Pour une position automatique, inscrivez loc='best'


Vous trouverez peut-être fastidieux d'avoir à créer une commande pour chaque catégorie que vous devez préalablement extraire, alors que vous désirez un seul nuage de point, dont la couleur est déterminée par la colonne species. Vous avez raison. C'est le désavantage de travailler en mode impératif. Nous verrons plus loin comment travailler en mode déclaratif.

Annoter une figure

Si vous avez à annoter une figure, vous utiliserez la fonction plt.annotate.


In [12]:
plt.plot(iris.sepal_length, iris.sepal_width, 'o')
plt.annotate('Setosa', #texte
             xytext=[4.5, 4.3], # s'il y a une flèche, emplacement du départ de la flèche et du texte
             xy=[5.0, 3.5], # endroit où pointe la flèche, ou s'il n'y a pas de flèche emplacement du texte 
             arrowprops={'color': 'gray'}) # propriétés de la flèche


Out[12]:
Text(4.5,4.3,'Setosa')

Enregistrer un graphique

Certains graphiques sont destinés à rester dans un notebook, d'autres devront être exportés pour être intégrer dans d'autres médias. Vous pouvez exporter les figures avec un clic droit, puis enregistrer l'image..., mais la fonction savefig() permettra davantage d'options, comme exporter un graphique avec une haute résolution avec l'argument dpi (dots per inch).


In [13]:
plt.plot(iris.sepal_length, iris.sepal_width, 'o')
plt.savefig('images/ma_figure.png', dpi=300)


J'ai utilisé le format d'image png, utile pour les images de type graphique, avec des changements de couleurs drastiques. Pour les photos, vous préférerez le format jpg. Des éditeurs demandront peut-être des formats vectoriels comme pdf ou eps. Si vous désirez éditer vos graphiques (bouger des étiquettes ou des légendes, ajouter des éléments graphiques), vous pouvez exporter voter graphique en format svg, puis l'éditer dans le logiciel libre Inkscape. Quoi qu'il en soit, voici les format d'exportation disponibles.


In [14]:
fig.canvas.get_supported_filetypes()


Out[14]:
{'eps': 'Encapsulated Postscript',
 'jpeg': 'Joint Photographic Experts Group',
 'jpg': 'Joint Photographic Experts Group',
 'pdf': 'Portable Document Format',
 'pgf': 'PGF code for LaTeX',
 'png': 'Portable Network Graphics',
 'ps': 'Postscript',
 'raw': 'Raw RGBA bitmap',
 'rgba': 'Raw RGBA bitmap',
 'svg': 'Scalable Vector Graphics',
 'svgz': 'Scalable Vector Graphics',
 'tif': 'Tagged Image File Format',
 'tiff': 'Tagged Image File Format'}

Seaborn

Les statistiques forment un pilier de l'écologie mathématique. La visualisation statistique permet d'interpréter et de communiquer vos résultats. Seaborn automatise la prodution des graphiques Matplotlib: quelques instructions suffisent pour créer des graphiques visuellement attrayants, prêts à être exportés pour la production de rapports et de publications scientifiques. Seaborn fonctionne de paire avec Pandas, le module de gestion de données que nous avons couvert au chapitre précédent. Seaborn est conventionnellement importé avec l'alias sns (au cas où vous voudriez savoir pourquoi).


In [15]:
import seaborn as sns

Courbes de tendance

Au prochain chapitre, nous nous intéresserons aux biostatistiques. La régression linéaire est un des outils statistiques les plus courramment utilisés. Une régression linéaire consiste à faire passer une droite à travers les données en minimisant les écarts entre la droite et les données. Reprenons le tableau des iris. Seaborn permet de tracer une droite à travers les points, par exemple entre la largeur et la longueur des pétales. Je change le style pour rendre le graphique plus lisible.


In [16]:
#plt.style.use('seaborn-white')
sns.lmplot(x='petal_width', y='petal_length', data=iris)


Out[16]:
<seaborn.axisgrid.FacetGrid at 0x7f2da666d278>

La bande de part et d'autre de la droite est une région de confiance de la régression. Nous verrons comment interpréter cette région dans le prochain chapitre.

Le paradoxe de Simpson stipule que la tendance d'un phénomène peut être radicalement différente lorsqu'on y ajoute une information catégorielle. En effet, pour les données d'iris, la relation entre les variables de dimensions des pétales devrait être différente selon l'espèce. C'est ici qu'entre en jeu l'aspect déclaratif de Seaborn. En mode impératif, nous générerions une ligne par espèce. Mais en mode déclaratif, nous utilisons l'information d'une colonne pour segmenter le graphique en différents éléments. Par exemple, nous utilisons l'information de l'espèce pour segmenter la régression de lmplot selon différentes couleurs, spécifiées par l'argument hue.


In [17]:
sns.lmplot(x='petal_width', y='petal_length', hue='species', data=iris)


Out[17]:
<seaborn.axisgrid.FacetGrid at 0x7f2da5d92a90>

De la même manière, une information peut être utilisée pour segmenter la régression dans une grille de graphique (on parle alors de trellis ou de facet). La segmentation des graphiques en lignes se fera avec l'argument row, et celle par colonne avec l'argument col (les deux peuvent être utilisées de paire).


In [18]:
sns.lmplot(x='petal_width', y='petal_length', col='species', data=iris)


Out[18]:
<seaborn.axisgrid.FacetGrid at 0x7f2da6581390>

Distributions univariées

De la même manière, Seaborn peut être utilisé pour visualiser des distributions. Les graphiques de distribution les plus commun sont les histogrammes, les courbes de densités, les boxplots et une combinaison des deux: les graphiques en violon.


In [19]:
plt.figure(figsize=[15, 4])
plt.subplot(141)
sns.distplot(iris['petal_width'], hist=True, kde=False)
plt.subplot(142)
sns.distplot(iris['petal_width'], hist=False, kde=True)
plt.subplot(143)
sns.boxplot(x='species', y='petal_width', data=iris)
plt.subplot(144)
sns.violinplot(x='species', y='petal_width', data=iris)

plt.subplots_adjust(wspace=0.4, hspace=None) # si plt.tight_layout ne fonctionne pas bien


Remarquez que la fonction sns.distplot ne prend pas en charge le mode déclaratif, pourtant bien utile. Dans les cas ou les trellis ne sont pas disponibles à même les fonctions graphiques, nous devons utiliser la fonction FacetGrid.


In [20]:
sns.FacetGrid(data=iris, hue="species", size=5, aspect=1.5).\
  map(sns.distplot, "petal_width", hist=False, kde=True, rug=True)


Out[20]:
<seaborn.axisgrid.FacetGrid at 0x7f2da653ea58>

Il faut d'abord invoquer FacetGrid, identifier la manière de segmenter (hue pour segmenter en différentes couleurs, row et col pour segmenter en lignes et en colonnes, respectivement), puis d'identifier le graphique à cartographier dans la segmentation, ici un distplot. Au lieu d'utiliser figsize pour contrôler la dimension du graphique, avec FacetGrid l'argument size définit la dimension du graphique et l'argument aspect défini le ratio largeur / longueur.

Distributions multivariées

La plupart des données écologiques sont multivariées, c'est-à-dire qu'ils contiennent plusieurs variables. Dans le cas de visualisations bivariées, il est commun de présenter un graphique présentant la relation entre deux variables, ainsi que les distributions marginales. Nous parlons alors de joint plots.


In [21]:
sns.jointplot(data=iris, x='petal_width', y='petal_length') # exercice: ajouter l'argument kind='kde'


Out[21]:
<seaborn.axisgrid.JointGrid at 0x7f2da6602be0>

Le graphique affiche la corrélation de Pearson ainsi que la p-value, des statistiques qui seront couvertes au prochain chapitre. Le diagramme en paires (pairs plot) est une généralisation du joint plot. Les colonnes non-numériques sont ignorées.


In [22]:
sns.pairplot(iris, hue="species") # essayez d'ajouter l'argument diag_kind="kde"


Out[22]:
<seaborn.axisgrid.PairGrid at 0x7f2da6142d68>

À venir

  • Séries temporelles
  • Cartes
  • Barres
**Exporter un graphique**. Pour envoyer un graphique à un.e collègue ou pour l'insérer dans un document, vous voudrez sans doute libérer votre graphique de votre carnet de calcul. Rapidement, avec un clic-droit, vous pouvez copier le graphique dans le presse-papier de votre environnement de travail, puis le coller où vous voulez. *altair* vous offre d'exporter le graphique en format PNG, qui est un format bitmap (pixels). Mais ces deux options vous donneront des graphiques de basse résolution. Pour une résolution supérieure, choisissez "Open in Vega Editor". En haut à droite, sélectionnez le format SVG, puis téléchargez. Ce fichier est un format vectoriel (formes) qui peut être importé dans un logiciel de dessin (je vous suggère le logiciel libre [Inkscape](https://inkscape.org)), puis exporté en bitmap à haute résolution ou en format vectoriel EPS ou PDF. Par ailleurs, un bon logiciel de dessin vectoriel, comme Inkscape, vous permettra d'éditer le graphique (par exemple, déplacer la légende) ou de l'annoter.

Les graphiques comme outil d'exploration des données

La plupart des graphiques que vous créerez ne seront pas destinés à être publiés, mais serviront d'outil d'exploration des données. Le jeu de données datasaurus, présenté en début de section, permet de saisir l'importance des outils graphiques pour bien comprendre les données.


In [23]:
datasaurus = pd.read_csv('data/DatasaurusDozen.tsv', sep='\t')
datasaurus.sample(5)


Out[23]:
dataset x y
178 away 65.970857 72.744856
1733 wide_lines 68.193290 46.543541
977 high_lines 54.114532 17.673534
1026 dots 52.729247 51.201765
741 star 44.074061 34.553204

Projetons d'abord les coordonnées x et y sur un graphique. J'utilise FacetGrid ici, sachant que ce sera utile pour l'exploration.


In [24]:
sns.FacetGrid(data=datasaurus, size=5).\
    map(plt.plot, 'x', 'y', marker='o', linestyle='None', alpha=0.5)


Out[24]:
<seaborn.axisgrid.FacetGrid at 0x7f2da5b26b38>

Ce graphique pourrait ressembler à une distribution binormale, ou un coup de 12 dans une porte de grange. Mais on aperçoit des données allignées, parfois de manière rectiligne, parfois en forme d'ellipse. Le tableau datasaurus a une colonne d'information supplémentaire. Utilisons-la comme catégorie pour générer des couleurs différente.


In [25]:
sns.FacetGrid(data=datasaurus, hue='dataset', size=5).\
    map(plt.plot, 'x', 'y', marker='o', linestyle='None', alpha=0.5)


Out[25]:
<seaborn.axisgrid.FacetGrid at 0x7f2da5a27c50>

Ce n'est pas vraiment plus clair. Il y a toutefois des formes qui se dégage, comme des ellipse et des lignes. Et si je regarde bien, j'y vois une étoile. La catégorisation pourrait-elle être mieux utilisée si on segmetnait par colonne au lieu de des couleurs?


In [26]:
sns.FacetGrid(data=datasaurus, col='dataset', col_wrap=4).\
    map(plt.plot, 'x', 'y', marker='o', linestyle='None')


Out[26]:
<seaborn.axisgrid.FacetGrid at 0x7f2da59ff080>

Voilà! Fait intéressant, ni les statistiques, ni les algorithmes de regroupement ne nous auraient été utiles pour différencier les groupes.

Autres modules

plotnine

J'ai présenté un aperçu de Seaborn, étant donné que ce module est largement utilisé en Python. Mais lorsque vient le temps de créer des graphiques, je préfère plotnine (étant à l'aise avec ggplot2 sur R).


In [27]:
from plotnine import *
ggplot(data=iris, mapping=aes(x='petal_width', y='petal_length')) +\
    facet_grid('species ~ .') +\
    stat_smooth(aes(colour='species'), method='lm') +\
    geom_point(aes(colour='species'))


/home/essicolo/bin/anaconda3/lib/python3.6/site-packages/statsmodels/compat/pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
  from pandas.core import datetools
Out[27]:
<ggplot: (-9223363297236459246)>

Plotly

Plotly offre des options avancées pour les graphiques intéractif.


In [28]:
from plotly.offline import download_plotlyjs, init_notebook_mode, iplot
import plotly.figure_factory as ff
init_notebook_mode(connected=True)

fig = ff.create_facet_grid(
    iris,
    x='petal_width',
    y='petal_length',
    facet_row='species',
    color_name='species',
    ggplot2=True
)
iplot(fig, filename='facet - ggplot2 style')


Altair

Un module intéressant, mais peu mature.


In [29]:
import altair as alt

alt.Chart(iris).mark_circle().encode(
    x='petal_width:Q',
    y='petal_length:Q',
    row='species:N',
    color='species:N'
)


Choisir les bonnes couleurs

La couleur est une information. Les couleurs devraient être sélectionnées d'abord pour être lisibles par les personnes ne percevant pas les couleurs, selon le support (apte à être photocopié, lisible à l'écran, lisible sur des documents imprimés en noir et blanc) et selon le type de données.

  • Données continues ou catégorielles ordinales: gradient (transition graduelle d'une couleur à l'autre), séquence (transition saccadée selon des groupes de données continues) ou divergentes (transition saccadée d'une couleur à l'autre vers des couleurs divergentes, par exemple orange vers blanc vers bleu).
  • Données catégorielles nominales: couleurs éloignées d'une catégorie à une autre (plus il y a de catégories, plus les couleurs sont susceptibles de se ressembler).
Capture d'écran de [colorbrewer2.org](http://colorbrewer2.org), qui propose des palettes de couleurs pour créer des cartes, mais l'information est pertinente pour tout type de graphique.

Un graphique exporté en format vectorel, en particulier ne format SVG, peut être édité dans un logiciel de dessin vectoriel. Il m'arrive de vouloir ajouter ou déplacer du texte manuellement. Dans ce cas, j'importe le fichier SVG du graphique dans le logiciel libre Inkscape.

Règles particulières

Les mauvais graphiques peuvent survenir à cause de l'ignorance, bien sûr, mais souvent ils existent pour la même raison que la boeuferie [bullhist] verbale ou écrite. Parfois, les gens ne se soucient pas de la façon dont ils présentent les données aussi longtemps que ça appuie leurs arguments et, parfois, ils ne se soucient pas que ça porte à confusion tant qu'ils ont l'air impressionnant. $-$ Carl Bergstorm et Jevin West, Calling Bullshit Read-Along Week 6: Data Visualization

Une représentation visuelle est un outil tranchant qui peut autant présenter un état véritable des données qu'une perspective trompeuse. Bien souvent, une ou plusieurs des 5 qualités ne sont pas respectées. Les occasions d'erreur ne manquent pas - j'en ferai mention dans la setion Choisir le bon type de graphique. Pour l'instant, notons quelques règles particulières.

Ne tronquez pas inutilement l'axe des $y$

Tronquer l'axe vertical peut amener à porter de fausses conclusions.

Effets sur la perception d'utiliser différentes références. Source: Yau (2015), [Real Chart Rules to Follow](https://flowingdata.com/2015/08/11/real-chart-rules-to-follow/).

La règle semble simple: les diagrammes en barre (utilisés pour représenter une grandeur) devraient toujours présenter le 0 et les diagrammes en ligne (utilisés pour présenter des tendances) ne requiert pas nécessairement le zéro ((Bergstrom et West, Calling bullshit: Misleading axes on graphs)[http://callingbullshit.org/tools/tools_misleading_axes.html]). Mais le zéro n'est pas toujours lié à une quantité particulière, par exemple, la température ou un log-ratio. De plus, avec un diagramme en ligne on pourra toujours magnifier des tendances en zoomant sur une variation somme toute mineure. On arrive donc moins à une règle qu'une qualité d'un bon graphique, en partcilier la qualité no 1 de Cairo: offrir une représentation honnête des données. Par exemple, Nathan Yau, auteur du blogue Flowing Data, propose de présenter des résultats de mannière relative à la mesure initiale. C'est d'ailleurs ce qui a été fait pour générer le graphique de Michael Mann et al., ci-dessus, où le zéro correspond à la moyenne des températures enregistrées entre 1961 et 1990.

Il peut être tentant de tronquer l'axe des $y$ lorsque l'on désire supperposer deux axes verticaux. Souvent, l'utilisation de plusieurs axes verticaux amène une perception de causalité dans des situations de fausses corrélations. On ne devrait jamais utiliser plusieurs axes verticaux. Ja-mais.

Utilisez un encrage proportionnel

Cette règle a été proposée par Edward Tufte dans Visual Display of Quantitative Information. Une des raisons pour lesquelles on évite de tronquer l'axe des $y$ en particulier pour les diagrammes en barre est que l'aire représentant une mesure (la quantité d'"encre" nécessaire pour la dessiner) devrait être proportionnelle à sa magnitude. Les diagrammes en barre sont particulièrement sensibles à cette règle, étant donnée que la largeur des barres peuvent amplifier l'aire occopée. Deux solutions dans ce cas: (1) utiliser des barres minces ou (2) préférer des "diagrammes de points" (dot charts, à ne pas confondre aux nuages de points).

L'encrage a beau être proportionnel, la difficulté que les humains éprouvent à comparer la dimension des cercles, et a fortiriori la dimension de parties de cercle, donne peu d'avantage à utiliser des diagrammes en pointe de tarte, souvent utilisés pour illustrer des proportions. Nathan Yau suggère de les utiliser avec suspicions et d'explorer d'autres options.

Pour comparer deux proportions, une avenue intéressante est le diagramme en pente, suggéré notamment par Ann K. Emery.

Par extension, le diagramme en pente devient un diagramme en ligne lorsque plusieurs types de proportions sont comparées, ou lorsque des proportions évoluent selon des données continuent.

De la même manière, les diagrammes en bulles ne devraient pas être représentatifs de la quantité, mais plutôt de contextualiser des données. Justement, le graphique tiré des données de Gap minder présenté plus haut est une contextualisation: l'aire d'un cercle ne permet pas de saisir la population d'un pays, mais de comparer grossièrement la population d'un pays par rapport aux autres.

Publiez vos données

Vous avez peut-être déjà feuilleté un article et voulu avoir accès aux données incluses dans un graphique. Il existe des outils pour digitaliser des graphiques pour en extraire les données. Mais le processus est fastidieux, long, souvent peu précis. De plus en plus, les chercheurs sont encouragés à publier leurs données et leurs calculs. Matplotlib et Seaborn sont des outils graphiques classiques qui devraient être accompagnés des données et calculs ayant servi à les générer. Mais ce n'est pas idéal non plus. En revanche, les outils graphiques modernes comme Plotly et Altair peuvent être exportés en code javascipt, qui contient toutes les informations sur les données et la manière de les représenter graphiquememt. Ce chapitre a pour objectif de vous familiarisre avec les outils de base les plus communément utilisés en calcul scientifique avec Python, mais je vous encourage à explorer la nouvelle génération d'outils graphiques.

Évitez de distraire avec des décorations futiles

À venir.

Visitez www.junkcharts.typepad.com de temps à autre

Le statisticien et blogueur Kaiser Fung s'affaire quotidiennement à proposer des améliorations à de mauvais graphiques sur son blogue Junk Charts.


In [ ]: