Graphiques#

Dans la foulée de premiers graphiques, nous approfondissons dans cette fiche la construction de graphiques avec Matplotlib pour visualiser des données. Nous regarderons successivement comment tracer des graphes de fonctions à une variable, des nuages de points avec barres d’erreur, des diagrammes en barre, et des histogrammes. Pour cela, nous nous appuierons sur la bibliothèque numpy. La table suivante résume les fonctionalités de Matplotlib que nous aurons parcourues.

Commandes et options essentielles de la bibliothèque Matplotlib

  • import matplotlib.pyplot as plt: import de la bibliothèque.

  • %matplotlib widget: permet l’affichage de figure interactives.

  • plt.ioff(): évite l’affichage implicite de figure.

  • fig, ax = plt.subplots(): construction d’une figure.

  • ax.scatter(x, y, **options): dessin d’un nuage de points.

  • ax.plot(x, y, **options): dessin d’une ligne brisée.

  • ax.errorbar(x, y, **options): dessin d’un nuage de points avec barres d’erreur.

  • ax.bar(x, y, **options): dessin d’un diagramme en barres.

  • ax.hist(data, bins=4, **options): dessin d’un histogramme.

  • ax.set_xlim(xmin, xmax) : limite l’axe des abscisses entre les valeurs xmin et xmax.

  • ax.set_ylim(ymin, ymax) : limite l’axe des ordonnées entre les valeurs ymin et ymax.

  • ax.set_xscale('log'): axe des abscisses en échelle logarithmique.

  • ax.set_yscale('log'): axe des ordonnées en échelle logarithmique.

  • ax.set_xlabel('texte') : donne un titre à l’axe des abscisses.

  • ax.set_ylabel('texte'): donne un titre à l’axe des ordonnées.

  • ax.set_title('texte'): définit le titre du graphique.

  • ax.grid(): dessin d’une grille de fond.

  • ax.legend(): ajout d’une légende en se basant sur les options label de scatter, plot, etc.

  • fig.show(): affiche la figure interactive.

Options:

  • color: définit la couleur des points ou de la courbe; à choisir parmi “green”, “blue”, “red”, “black”, etc, ou “g”, “b”, “r”, “k”, etc.

  • linestyle: définit le style du trait: “-” (trait continu), “–” (tireté), “:” (pointillé) ou “None” (aucun trait).

  • marker: définit le style des points: “.” (point), “o” (rond), “*” (étoile), “d” (diamant), etc.

  • label: donne un nom au tracé pour construire une légende par la suite.

Graphes de fonctions à une variable#

On souhaite tracer le graphe de la fonction à une variable suivante:

\[\begin{split}\text{parabole}: \begin{cases} \mathbb{R} & \rightarrow \mathbb{R}\\ x &\mapsto x^2 \end{cases} \,.\end{split}\]

En Python, cette fonction s’écrit:

def parabole(x):
    return x ** 2

Graphes de fonctions avec des listes#

Procédons d’abord au plus simple, comme dans la feuille précédente:

import matplotlib.pyplot as plt
%matplotlib widget
plt.ioff();
x_list = list(range(-5, 5))
y_list = [parabole(x) for x in x_list]

fig, ax = plt.subplots()
ax.plot(x_list, y_list)
fig.show()

C’est un peu décevant:

  • La courbe n’est pas lisse: on n’a en effet pas tracé stricto sensu le graphe de la fonction mathématique, mais une approximation de celui-ci par une ligne brisée. Il n’est en effet pas possible de représenter dans une machine des informations continues qui sont infinies. On dit que l’on a discrétisé le graphe la fonction.

  • Le graphe ne va que de -5 à +4.

  • La figure est pauvre en information (pas de noms sur les axes, de titre, de légende).

Exercice

Améliorez ci-dessous le graphe ci-dessus:

  • Augmentez le nombre de points.
    Indication: utilisez une compréhension pour construire la liste x_list contenant [-5, -4.9, -4.8, ..., 4.9, 5].

  • Assurez vous que le graphe aille de -5 à +5.

  • Nommez les axes et ajoutez un titre et une légende.
    Indication: consultez le rappel des commandes essentielles ci-dessus, ainsi que les exemples de la fiche premiers graphiques.

### BEGIN SOLUTION
x_list = [-5 + i * .1 for i in range(101)]
y_list = [parabole(x) for x in x_list]

fig, ax = plt.subplots()
ax.plot(x_list, y_list, label=r"$x \mapsto x^2$")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_title("Une parabole")
ax.legend()
### END SOLUTION
fig.show()

Graphes de fonctions avec numpy#

Le tracé de graphes comme ci-dessus nous amène à manipuler de grands tableaux numériques. Aussi, pour plus de performance et de flexibilité, il est recommandé d’utiliser des tableaux numpy plutôt que des listes.

import numpy as np

Pour construire la liste des abscisses, on peut utiliser la fonction linspace, Elle est analogue à range, à part que l’on spécifie le nombre de points et non le pas et que la dernière valeur est incluse:

x = np.linspace(-5, 5, 11)
x
array([-5., -4., -3., -2., -1.,  0.,  1.,  2.,  3.,  4.,  5.])

Pour construire la liste des ordonnées, on peut utiliser la vectorisation: lorsqu’on opération arithmétique est appliquée au tableau, elle est en fait appliquée à tous les éléments du tableau, et ce très rapidement.

y = parabole(x)
y
array([25., 16.,  9.,  4.,  1.,  0.,  1.,  4.,  9., 16., 25.])

Attention

Les notations ci-dessus sont traditionnelles mais peuvent porter à confusion: l’instruction y = parabole(x) ne calcule pas l’ordonnée \(y\) d’un point d’abscisse \(x\) mais toutes les ordonnées d’un coup de tous les points dont les abscisses sont données dans le tableau x.

Le graphique se construit ensuite comme précédemment:

fig, ax = plt.subplots()
ax.plot(x, y)
fig.show()

Exercice

Reproduisez, en utilisant des tableaux numpy comme ci-dessus, la figure améliorée de l’exercice précédent.

### BEGIN SOLUTION
x = np.linspace(-5, 5, 100)
y = parabole(x)

fig, ax = plt.subplots()
ax.plot(x, y, label=r"$x \mapsto x^2$")
ax.set_xlabel("x")
ax.set_ylabel("y")
ax.set_title("Une parabole")
ax.legend()
### END SOLUTION
fig.show()

Effet de la discrétisation#

Pour conclure sur les graphes de fonctions, nous observons l’effet de la discrétisation en traçant la fonction \(\sin x\) entre \(-\pi\) et \(\pi\), avec un nombre croissant de points:

import matplotlib.pyplot as plt
from numpy import pi, sin

xmin = -pi
xmax = pi
npoints = [2, 4, 8, 16, 32, 64, 128]
 
fig, ax = plt.subplots()

for n in npoints :
    x = np.linspace(xmin, xmax, n)
    y = sin(x)
    plt.plot(x, y, label=f'npoints: {n}')

ax.set_xlabel('x')
ax.set_ylabel('sin(x)')
ax.set_title('Discrétisation et sinus')
ax.legend(loc="lower right")
fig.show()

Tracé de mesures avec leurs incertitudes#

La bibliothèque Matplotlib contient aussi une fonction errorbar pour tracer des mesures avec des barres d’erreur indiquant leurs incertitudes. Elle prend pour arguments principaux :

  • x et y: les abscisses et ordonnées des mesures (comme pour plot).

  • xerr et yerr (optionnels): les incertitudes respectives sur l’axe des abscisses et des ordonnées.

Exemple

On souhaite visualiser des mesures d’un courant \(I\) traversant une résistance \(R\) alimentée par une tension \(U=5\) V à ses bornes, pour différentes valeurs de \(R\) mesurées à l’ohmètre (dont la notice indique une incertitude de \(10\%\)) et les comparer à une courbe théorique.

# Valeurs mesurées et incertitudes sur R
R = [12.05, 100.2, 998.7, 10987 ] 
R_err = [r*0.1 for r in R ]

# Valeurs mesurées et incertitudes sur I 
I = [0.45, 0.053, 0.0046, 4.7e-4 ] 
I_err = [0.08, 0.013, 23e-4, 9e-5 ] 

# Courbe théorique
U = 5.
I_theo = [U/r for r in R]

# Visualisation
fig, ax = plt.subplots()
ax.errorbar(R, I,
    xerr=R_err,
    yerr= I_err, 
    marker='.', color='r',
    linestyle='None',
    label='Mesures')
ax.plot(R, I_theo, color='b', label='Courbe théorique')
ax.set_title('Mesure de I(R)')
ax.set_xlabel('R [Ohms]')
ax.set_ylabel('I [A]')
ax.set_xscale('log')        # échelle logarithmique en x
ax.set_yscale('log')        # échelle logarithmique en y
ax.grid()
ax.legend()
fig.show()

Représentation en diagramme en barres ou circulaires#

L’œil humain a une capacité naturelle à comparer les grandeurs visuelles (longueurs, surfaces, angles). Plusieurs types de graphiques, comme les diagramme en barres (ou en bâtons), ou circulaires (ou en camemberts), exploitent cette capacité pour comparer visuellement des quantités; par exemple pour comparer plusieurs catégories en absolu ou relatif, montrer l’évolution d’une même catégorie sur le temps ou repérer les tendances (hausse, baisse, stabilité). Pour dessiner de tels diagramme, les fonctions bar et pie – les anglophones préfèrent les tartes aux camemberts – prennent pour arguments principaux:

  • x: les noms des catégories.

  • y: les quantités pour chaque catégorie.

  • color: les couleurs souhaitées pour les catégories.

Exemple

Le diagramme suivant représente l’état des stocks de quelques fruits chez un commerçant, en absolu (diagramme en barre) et en relatif (diagramme circulaire).

fruits = ['fraises', 'abricots', 'cerises', 'myrtilles']
weights = [4, 10, 3, 5.5]
colors = ['pink', 'orange', 'red', 'blue']

fig, (ax1, ax2) = plt.subplots(1,2)

ax1.bar(fruits, weights, color=colors)
ax1.set_ylabel('kg')
ax1.set_title('Stocks de fruits')

ax2.pie(weights, labels=fruits, colors=colors)
ax2.set_title('Stocks relatifs de fruits')

fig.show()

Histogrammes#

Un histogramme est un cas particulier de diagramme en barres qui prend en charge le regroupement des données en catégories. Pour en tracer un, la méthode hist admet pour arguments principaux:

  • data: la série de données dont on veut représenter l’histogramme.

  • bins (optionnel): pour des données numériques, les intervalles ou le nombre d’intervalles désirés.

Exemple

Nous traçons un histogramme pour des notes à une interrogation, avec dix intervalles déterminés automatiquement:

notes = [8.5, 12.5, 11, 10, 13.5, 5, 18, 16.5, 12, 13, 11,
    9, 10, 4, 20, 12.5, 10.5, 7, 8.5, 13.5, 15.5 ]
 
fig, ax = plt.subplots()
ax.hist(notes, bins=10) 
ax.set_title('Notes interrogation')
ax.set_xlabel('Notes')
ax.set_ylabel('Nombre')
ax.grid()
fig.show()

ou avec des intervalles de 5 points:

bins = [0, 5, 10, 15, 20]  # intervalles
 
fig, ax = plt.subplots()
ax.hist(notes, bins=bins)
ax.set_title('Notes interro')
ax.set_xlabel('Notes')
ax.set_ylabel('Nombre')
ax.grid()
fig.show()

Exemple

Nous traçons maintenant un histogramme pour des données non numériques: la distribution des bases “A”, “C”, “G”, “T” dans une séquence d’ADN.

sequence = "ACGATCATAGCGAGCTACGTAGAA"

fig, ax = plt.subplots()
ax.hist(list(sequence))    # Noter la conversion en une liste de caractères
ax.set_xlabel("Bases")
ax.set_ylabel("Nombre")
ax.set_title(f"Distribution des bases\n dans la séquence {sequence}")
fig.show()

Bilan#

Nous espèrons que ces courts exemples vous auront convaincu de l’utilité de la bibliothèque Matplotlib. Sachez qu’elle peut faire bien plus, y compris des graphiques en trois dimensions ou animés. Il existe par ailleurs d’autres outils pour produire des graphiques avec Python, par exemple directement à partir de tables Pandas, ou à l’aide de bibliothèques spécialisées comme Seaborn, bqplot, Bokeh ou Plotly. Ces trois dernières permettent de générer des graphiques interactifs, c’est-à-dire des graphiques dans lesquels on peut zoomer, se déplacer, changer les donnés au vol, etc. Nous vous invitons à les découvrir par vous-même.

Voir aussi

  • Le site de Matplotlib fournit de nombreux exemples détaillés, n’hésitez pas à le consulter.

  • Le site Python Graph Gallery propose aussi des exemples de code pour différents types de graphiques, réalisés avec Matplotlib ou d’autres bibliothèques.

  • Enfin, des cheat sheets de Matplotlib sont extrêmement utiles et très bien faites.