Premiers graphiques
«Un bon croquis vaut mieux qu’un long discours». Cela vaut aussi en analyse des données: la visualisation est un outil fondamental pour observer, explorer, synthétiser, comprendre les données et pour transmettre cette compréhension. Dans cette fiche, nous allons découvrir la bibliothèque matplotlib qui permet de réaliser en quelques lignes de jolis graphiques.
Remerciements
Cette fiche est fortement inspirée du début du chapitre Matplotlib du cours «Introduction à la programmation Python pour la biologie» (sources). Quelques éléments ont été repris du cours Introduction à la Science des Données.
Visualisation de données par un nuage de points¶
Dans cet exemple -- purement fictif -- nous considérons des données mesurant l’évolution de la concentration d’un produit dans le sang (exprimé en mg/L) en fonction du temps (exprimé en heures):
Mesures
| Temps (h) | Concentration (mg/L) |
|---|---|
| 1 | 3.5 |
| 2 | 5.8 |
| 3 | 9.1 |
| 4 | 11.8 |
| 6 | 17.5 |
| 7 | 21.3 |
| 8 | 3.2 |
| 9 | 26.8 |
Nous allons maintenant représenter l’évolution de la concentration en fonction du temps:
import matplotlib.pyplot as plt
%matplotlib widget
plt.ioff()
temps = [1, 2, 3, 4, 6, 7, 8, 9]
concentration = [5.5, 7.2, 11.8, 13.6, 19.1, 21.7, 3.2, 29.4]
fig, ax = plt.subplots()
ax.scatter(temps, concentration, marker="o", color="blue")
ax.grid()
ax.set_xlabel("Temps (h)")
ax.set_ylabel("Concentration (mg/L)")
ax.set_title("Concentration de produit en fonction du temps")
fig.show()On appelle une telle figure un nuage de points. Chaque point représente une mesure: son abscisse indique le temps et son ordonnée la concentration mesurée. Par exemple, le premier point correspond à la mesure effectuée au bout d’une heure, où la concentration était de 5.5 mg/L.
Reprenons pas à pas ce code. Tout d’abord, on importe le sous-module pyplot de la
bibliothèque Matplotlib et on lui donne l’alias plt pour l’utiliser plus commodément
ensuite. Cet alias est standard, utilisez-le systématiquement. La commande
%matplotlib widget permet d’avoir des figures interactives (possibilité de
redimensioner, de zoomer, ...). La commande plt.ioff() permet de contrôler
explicitement quand la figure est affichée.
import matplotlib.pyplot as plt
%matplotlib widget
plt.ioff()On définit ensuite deux listes temps et concentration contenant les valeurs
respectives du temps et de la concentration lors de chaque mesure. Ces deux listes
doivent avoir la même longueur (sept éléments dans le cas présent):
temps = [1, 2, 3, 4, 6, 7, 8, 9]
concentration = [5.5, 7.2, 11.8, 13.6, 19.1, 21.7, 40.2, 29.4]On crée une figure avec la fonction subplots() qui renvoie deux objets : une figure
(fig) et un graphique (ax):
fig, ax = plt.subplots()Pour le moment, la figure est vide:
figLa méthode .scatter() permet de représenter un nuage de points sur le graphique. Les
deux premiers arguments correspondent respectivement aux abscisses et aux ordonnées des
points. Des arguments facultatifs sont ensuite précisés comme le symbole (marker) et la
couleur (color).
ax.scatter(temps, concentration, marker="o", color="blue")
figLa méthode .grid ajoute une grille de fond:
ax.grid()
figLes méthodes .set_xlabel() et .set_ylabel() définissent la légende des axes des
abscisses et des ordonnées:
ax.set_xlabel("Temps (h)")
ax.set_ylabel("Concentration (mg/L)")
figLa méthode .set_title() définit le titre du graphique:
ax.set_title("Concentration de produit en fonction du temps")
figEnfin la méthode .show() affiche la figure avec interactivité:
fig.show()### BEGIN SOLUTION
ax.set_ylabel("Concentration (cg/L)")
### END SOLUTION
figassert "cg/L" in ax.yaxis.label._text, "La légende des ordonnées devrait contenir cg/L"### BEGIN SOLUTION
temps = [1, 2, 3, 4, 6, 7, 9]
concentration = [5.5, 7.2, 11.8, 13.6, 19.1, 21.7, 29.4]
fig, ax = plt.subplots()
ax.scatter(temps, concentration, marker="o", color="blue")
ax.grid()
ax.set_xlabel("Temps (h)")
ax.set_ylabel("Concentration (cg/L)")
ax.set_title("Concentration de produit en fonction du temps")
### END SOLUTION
fig.show()assert len(temps) == 7
assert len(concentration) == 7
assert 8 not in temps
assert ax.xaxis.label._text == "Temps (h)", "Légende des abscisses incorrecte"
assert ax.yaxis.label._text == "Concentration (cg/L)", (
"Légende des ordonnées incorrecte"
)
assert ax.title._text == "Concentration de produit en fonction du temps", (
"titre incorrect"
)Visualisation d’une courbe¶
Revenons sur notre expérience. On suppose que l’évolution de la concentration du produit en fonction du temps peut-être modélisée par la fonction exprimant la concentration en fonction du temps. Pour comparer ce modèle théorique avec nos données, nous allons compléter la figure précédente en y superposant un graphe de la fonction sous forme d’une courbe.
Pour cela, il suffit de définir la fonction C(t):
def C(t):
return 2 + 3 * tde calculer la concentration théorique à chaque pas de temps en utilisant une compréhension:
concentration_théorique = [C(t) for t in temps]et d’utiliser la méthode .plot() pour construit une courbe -- en fait une ligne brisée
-- à partir des coordonnées en abscisse et en ordonnées des points à représenter; les
arguments facultatifs de spécifient le style de la ligne (linestyle) et sa couleur
(color):
ax.plot(temps, concentration_théorique, color="green", linestyle="--")
fig.show()La cellule suivante résume la construction complète de la figure, en ajoutant une légende et en modifiant l’étendue des axes des abscisses et des ordonnées:
import numpy as np
import matplotlib.pyplot as plt
temps = [1, 2, 3, 4, 6, 7, 9]
concentration = [5.5, 7.2, 11.8, 13.6, 19.1, 21.7, 29.4]
def C(t):
return 2 + 3 * t
concentration_théorique = [C(t) for t in temps]
fig, ax = plt.subplots()
ax.scatter(temps, concentration, marker="o", color="blue", label="mesures")
ax.plot(temps, concentration_théorique, color="green", linestyle="--", label="modèle")
ax.set_xlim(0, 10) # Étendue de l'axe des x
ax.set_ylim(0, 35)
ax.grid()
ax.set_xlabel("Temps (h)")
ax.set_ylabel("Concentration (g/L)")
ax.set_title("Concentration de produit en fonction du temps")
ax.legend(loc="upper left")
fig.show()Nous enregistrons maintenant la figure (méthode savefig) sous la forme d’une image au
format svg. Les arguments optionnels configurent les marges autour du graphique
(bbox_inches) ainsi que la résolution de l’image (dpi):
fig.savefig("media/concentration_vs_temps.svg", bbox_inches="tight", dpi=200)Vous pouvez maintenant retrouver la figure dans le fichier
media/concentration_vs_temps.svg.
Bilan¶
Dans cette fiche, nous avons vu comment construire un graphique, avec un nuage de points
(scatter) et une courbe (plot) représentant respectivement des données de mesures et
un modèle théorique. Nous avons aussi vu comment enrichir ce graphique en configurant les
axes (set_xlim, set_ylim, set_xlabel, set_ylabel), choisissant le style (grid,
marker, color, ls) et ajoutant une légende et un titre (set_title).
import matplotlib.pyplot as plt
temps = [1, 2, 3, 4, 6, 7, 8, 9]
concentration = [5.5, 7.2, 11.8, 13.6, 19.1, 21.7, 40.2, 29.4]
plt.figure()
plt.scatter(temps, concentration, marker="o", color="blue")
plt.grid()
plt.xlabel("Temps (h)")
plt.ylabel("Concentration (mg/L)")
plt.title("Concentration de produit en fonction du temps");