11. Matplotlib#

11.1. Vue d’ensemble#

Nous avons déjà produit un certain nombre de figures dans ces cours en utilisant Matplotlib.

Matplotlib est une bibliothèque graphique remarquable, conçue pour le calcul scientifique, avec

  • des graphiques 2D et 3D de haute qualité

  • une sortie dans tous les formats habituels (PDF, PNG, etc.)

  • une intégration LaTeX

  • un contrôle fin de tous les aspects de la présentation

  • de l’animation, etc.

11.1.1. La double personnalité de Matplotlib#

Matplotlib est inhabituelle dans le sens où elle offre deux interfaces différentes pour tracer des graphiques.

L’une est une simple API (Application Programming Interface) de style MATLAB, qui a été écrite pour aider les réfugiés de MATLAB à trouver un environnement familier.

L’autre est une API orientée objet plus « pythonique ».

Pour les raisons décrites ci-dessous, nous vous recommandons d’utiliser la seconde API.

Mais commençons par discuter de la différence.

11.2. Les API#

11.2.1. L’API de style MATLAB#

Voici le genre d’exemple simple que vous pourriez trouver dans les traitements introductifs

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 200)
y = np.sin(x)

plt.plot(x, y, 'b-', linewidth=2)
plt.show()
_images/abeb4cb1edbad1dc9730e37d6bcdeed8be3806eeccdfde6decf42c64cc1d5f22.png

C’est simple et pratique, mais aussi quelque peu limité et peu pythonique.

Par exemple, dans les appels de fonction, beaucoup d’objets sont créés et transmis sans se faire connaître du programmeur.

Les programmeurs Python tendent à préférer un style de programmation plus explicite (exécutez import this dans un bloc de code et regardez la deuxième ligne).

Cela nous conduit à l’API alternative, orientée objet, de Matplotlib.

11.2.2. L’API orientée objet#

Voici le code correspondant à la figure précédente en utilisant l’API orientée objet

fig, ax = plt.subplots()
ax.plot(x, y, 'b-', linewidth=2)
plt.show()
_images/abeb4cb1edbad1dc9730e37d6bcdeed8be3806eeccdfde6decf42c64cc1d5f22.png

Ici, l’appel fig, ax = plt.subplots() renvoie une paire, où

  • fig est une instance de Figure — comme une toile vierge.

  • ax est une instance d”AxesSubplot — pensez à un cadre dans lequel tracer.

La fonction plot() est en réalité une méthode de ax.

Bien qu’il y ait un peu plus de saisie, l’utilisation plus explicite des objets nous donne un meilleur contrôle.

Cela deviendra plus clair au fur et à mesure.

11.2.3. Ajustements#

Ici, nous avons changé la ligne en rouge et ajouté une légende

fig, ax = plt.subplots()
ax.plot(x, y, 'r-', linewidth=2, label='fonction sinus', alpha=0.6)
ax.legend()
plt.show()
_images/6350efa358887cedd431688e570fa450cbf97b5483bd3120ac5283f6d5c45072.png

Nous avons également utilisé alpha pour rendre la ligne légèrement transparente — ce qui la fait paraître plus lisse.

L’emplacement de la légende peut être modifié en remplaçant ax.legend() par ax.legend(loc='upper center').

fig, ax = plt.subplots()
ax.plot(x, y, 'r-', linewidth=2, label='fonction sinus', alpha=0.6)
ax.legend(loc='upper center')
plt.show()
_images/8aec5fe9db65b016c9ce46d501526e474b22ba8d5202af161e33ff20ecd790a5.png

Si tout est correctement configuré, alors ajouter du LaTeX est trivial

fig, ax = plt.subplots()
ax.plot(x, y, 'r-', linewidth=2, label=r'$y=\sin(x)$', alpha=0.6)
ax.legend(loc='upper center')
plt.show()
_images/e15823f6ed52a8c26dc57d2fab36459da1c66ba7ccc727be2420cd6f37565bf5.png

Contrôler les graduations, ajouter des titres, etc. est également simple

fig, ax = plt.subplots()
ax.plot(x, y, 'r-', linewidth=2, label=r'$y=\sin(x)$', alpha=0.6)
ax.legend(loc='upper center')
ax.set_yticks([-1, 0, 1])
ax.set_title('Graphique de test')
plt.show()
_images/673442cf145eb7cd0ba71e4421044a972a77233b343a5c40c42695fbe10dfff2.png

11.3. Fonctionnalités supplémentaires#

Matplotlib dispose d’un vaste ensemble de fonctions et de fonctionnalités, que vous pourrez découvrir au fil du temps selon vos besoins.

Nous n’en mentionnons que quelques-unes.

11.3.1. Plusieurs tracés sur un même axe#

Il est facile de générer plusieurs tracés sur les mêmes axes.

Voici un exemple qui génère aléatoirement trois densités normales et ajoute une étiquette avec leur moyenne

from scipy.stats import norm
from random import uniform

fig, ax = plt.subplots()
x = np.linspace(-4, 4, 150)
for i in range(3):
    m, s = uniform(-1, 1), uniform(1, 2)
    y = norm.pdf(x, loc=m, scale=s)
    current_label = rf'$\mu = {m:.2}$'
    ax.plot(x, y, linewidth=2, alpha=0.6, label=current_label)
ax.legend()
plt.show()
_images/b7073178bba98ebc63062c7b8410e8ae7f10373a4ad41e84cf2e4fced13f27ff.png

11.3.2. Plusieurs sous-graphiques#

Parfois, nous voulons plusieurs sous-graphiques dans une seule figure.

Voici un exemple qui génère 6 histogrammes

num_rows, num_cols = 3, 2
fig, axes = plt.subplots(num_rows, num_cols, figsize=(10, 12))
for i in range(num_rows):
    for j in range(num_cols):
        m, s = uniform(-1, 1), uniform(1, 2)
        x = norm.rvs(loc=m, scale=s, size=100)
        axes[i, j].hist(x, alpha=0.6, bins=20)
        t = rf'$\mu = {m:.2}, \quad \sigma = {s:.2}$'
        axes[i, j].set(title=t, xticks=[-4, 0, 4], yticks=[])
plt.show()
_images/bd2017ecf983c0a7e99c74bb774fcc2ec7ca353923b22dd5aa407ab6254f907c.png

11.3.3. Tracés 3D#

Matplotlib fait un bon travail pour les tracés 3D — en voici un exemple

from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib import cm


def f(x, y):
    return np.cos(x**2 + y**2) / (1 + x**2 + y**2)

xgrid = np.linspace(-3, 3, 50)
ygrid = xgrid
x, y = np.meshgrid(xgrid, ygrid)

fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(x,
                y,
                f(x, y),
                rstride=2, cstride=2,
                cmap=cm.jet,
                alpha=0.7,
                linewidth=0.25)
ax.set_zlim(-0.5, 1.0)
plt.show()
_images/8e79260b1d892170b9c2017fa016e9ffcbf12e632c5f94ca04ae4aa3e6c6e679.png

11.3.4. Une fonction de personnalisation#

Peut-être trouverez-vous un ensemble de personnalisations que vous utilisez régulièrement.

Supposons que nous préférions généralement que nos axes passent par l’origine et qu’ils comportent une grille.

Voici un bel exemple de Matthew Doty montrant comment l’API orientée objet peut être utilisée pour construire une fonction subplots personnalisée qui implémente ces changements.

Lisez attentivement le code et voyez si vous pouvez suivre ce qui se passe

def subplots():
    "Sous-graphiques personnalisés avec des axes passant par l'origine"
    fig, ax = plt.subplots()

    # Placer les axes de façon à ce qu'ils passent par l'origine
    for spine in ['left', 'bottom']:
        ax.spines[spine].set_position('zero')
    for spine in ['right', 'top']:
        ax.spines[spine].set_color('none')

    ax.grid()
    return fig, ax


fig, ax = subplots()  # Appeler la version locale, et non plt.subplots()
x = np.linspace(-2, 10, 200)
y = np.sin(x)
ax.plot(x, y, 'r-', linewidth=2, label='fonction sinus', alpha=0.6)
ax.legend(loc='lower right')
plt.show()
_images/df6cf7c9b164491bc8fd3b2b6f8bc8c774b436d3c6302d184cfab71c90160ee1.png

La fonction subplots personnalisée

  1. appelle en interne la fonction standard plt.subplots pour générer la paire fig, ax,

  2. effectue les personnalisations souhaitées sur ax, et

  3. renvoie la paire fig, ax au code appelant.

11.3.5. Feuilles de style#

Une autre fonctionnalité utile de Matplotlib est celle des feuilles de style.

Nous pouvons utiliser des feuilles de style pour créer des graphiques avec des styles uniformes.

Nous pouvons obtenir une liste des styles disponibles en affichant l’attribut plt.style.available

print(plt.style.available)
['Solarize_Light2', '_classic_test_patch', '_mpl-gallery', '_mpl-gallery-nogrid', 'bmh', 'classic', 'dark_background', 'fast', 'fivethirtyeight', 'ggplot', 'grayscale', 'petroff10', 'seaborn-v0_8', 'seaborn-v0_8-bright', 'seaborn-v0_8-colorblind', 'seaborn-v0_8-dark', 'seaborn-v0_8-dark-palette', 'seaborn-v0_8-darkgrid', 'seaborn-v0_8-deep', 'seaborn-v0_8-muted', 'seaborn-v0_8-notebook', 'seaborn-v0_8-paper', 'seaborn-v0_8-pastel', 'seaborn-v0_8-poster', 'seaborn-v0_8-talk', 'seaborn-v0_8-ticks', 'seaborn-v0_8-white', 'seaborn-v0_8-whitegrid', 'tableau-colorblind10']

Nous pouvons maintenant utiliser la méthode plt.style.use() pour définir la feuille de style.

Écrivons une fonction qui prend le nom d’une feuille de style et trace différents graphiques avec ce style

def draw_graphs(style='default'):

    # Définir une feuille de style
    plt.style.use(style)

    fig, axes = plt.subplots(nrows=1, ncols=4, figsize=(10, 3))
    x = np.linspace(-13, 13, 150)

    # Fixer les valeurs de graine pour reproduire les résultats des tirages aléatoires
    np.random.seed(9)

    for i in range(3):

        # Tirer la moyenne et l'écart-type à partir de lois uniformes
        m, s = np.random.uniform(-8, 8), np.random.uniform(2, 2.5)

        # Générer un tracé de densité normale
        y = norm.pdf(x, loc=m, scale=s)
        axes[0].plot(x, y, linewidth=3, alpha=0.7)

        # Créer un nuage de points avec des valeurs X et Y aléatoires 
        # tirées de lois normales
        rnormX = norm.rvs(loc=m, scale=s, size=150)
        rnormY = norm.rvs(loc=m, scale=s, size=150)
        axes[1].plot(rnormX, rnormY, ls='none', marker='o', alpha=0.7)

        # Créer un histogramme avec des valeurs X aléatoires
        axes[2].hist(rnormX, alpha=0.7)

        # et un graphique en ligne avec des valeurs Y aléatoires
        axes[3].plot(x, rnormY, linewidth=2, alpha=0.7)

    style_name = style.split('-')[0]
    plt.suptitle(f'Style : {style_name}', fontsize=13)
    plt.show()

Voyons à quoi ressemblent quelques-uns de ces styles.

D’abord, nous traçons des graphiques avec la feuille de style seaborn

draw_graphs(style='seaborn-v0_8')
_images/f6ff3579da7f8630c766bba474f18b91a6d31246b8386bb191159136ae99369f.png

Nous pouvons utiliser grayscale pour supprimer les couleurs des graphiques

draw_graphs(style='grayscale')
_images/c46ea882dd9f8f183de5682298c859b4fd304632a6a03d815e58fa8501259894.png

Voici à quoi ressemble ggplot

draw_graphs(style='ggplot')
_images/f5bcb04678b7c1cb33ad6ac5b07428eaab8d158bd348500c6ac2f10ab9e006d9.png

Nous pouvons aussi utiliser le style dark_background

draw_graphs(style='dark_background')
_images/5cd2d3052d3b8a9d1fb4bb9b5134851fdf9c63f7b188e8761ce51e7d93125542.png

Vous pouvez utiliser la fonction pour expérimenter avec d’autres styles de la liste.

Si cela vous intéresse, vous pouvez même créer vos propres feuilles de style.

Les paramètres de vos feuilles de style sont stockés dans une variable de type dictionnaire plt.rcParams

print(plt.rcParams.keys())

Hide code cell output

KeysView(RcParams({'_internal.classic_mode': False,
          'agg.path.chunksize': 0,
          'animation.bitrate': -1,
          'animation.codec': 'h264',
          'animation.convert_args': ['-layers', 'OptimizePlus'],
          'animation.convert_path': 'convert',
          'animation.embed_limit': 20.0,
          'animation.ffmpeg_args': [],
          'animation.ffmpeg_path': 'ffmpeg',
          'animation.frame_format': 'png',
          'animation.html': 'none',
          'animation.writer': 'ffmpeg',
          'axes.autolimit_mode': 'data',
          'axes.axisbelow': True,
          'axes.edgecolor': 'white',
          'axes.facecolor': 'black',
          'axes.formatter.limits': [-5, 6],
          'axes.formatter.min_exponent': 0,
          'axes.formatter.offset_threshold': 4,
          'axes.formatter.use_locale': False,
          'axes.formatter.use_mathtext': False,
          'axes.formatter.useoffset': True,
          'axes.grid': True,
          'axes.grid.axis': 'both',
          'axes.grid.which': 'major',
          'axes.labelcolor': 'white',
          'axes.labelpad': 4.0,
          'axes.labelsize': 'large',
          'axes.labelweight': 'normal',
          'axes.linewidth': 1.0,
          'axes.prop_cycle': cycler('color', ['#8dd3c7', '#feffb3', '#bfbbd9', '#fa8174', '#81b1d2', '#fdb462', '#b3de69', '#bc82bd', '#ccebc4', '#ffed6f']),
          'axes.spines.bottom': True,
          'axes.spines.left': True,
          'axes.spines.right': True,
          'axes.spines.top': True,
          'axes.titlecolor': 'auto',
          'axes.titlelocation': 'center',
          'axes.titlepad': 6.0,
          'axes.titlesize': 'x-large',
          'axes.titleweight': 'normal',
          'axes.titley': None,
          'axes.unicode_minus': True,
          'axes.xmargin': 0.05,
          'axes.ymargin': 0.05,
          'axes.zmargin': 0.05,
          'axes3d.automargin': False,
          'axes3d.grid': True,
          'axes3d.mouserotationstyle': 'arcball',
          'axes3d.trackballborder': 0.2,
          'axes3d.trackballsize': 0.667,
          'axes3d.xaxis.panecolor': (0.95, 0.95, 0.95, 0.5),
          'axes3d.yaxis.panecolor': (0.9, 0.9, 0.9, 0.5),
          'axes3d.zaxis.panecolor': (0.925, 0.925, 0.925, 0.5),
          'backend': 'module://matplotlib_inline.backend_inline',
          'backend_fallback': True,
          'boxplot.bootstrap': None,
          'boxplot.boxprops.color': 'white',
          'boxplot.boxprops.linestyle': '-',
          'boxplot.boxprops.linewidth': 1.0,
          'boxplot.capprops.color': 'white',
          'boxplot.capprops.linestyle': '-',
          'boxplot.capprops.linewidth': 1.0,
          'boxplot.flierprops.color': 'white',
          'boxplot.flierprops.linestyle': 'none',
          'boxplot.flierprops.linewidth': 1.0,
          'boxplot.flierprops.marker': 'o',
          'boxplot.flierprops.markeredgecolor': 'white',
          'boxplot.flierprops.markeredgewidth': 1.0,
          'boxplot.flierprops.markerfacecolor': 'none',
          'boxplot.flierprops.markersize': 6.0,
          'boxplot.meanline': False,
          'boxplot.meanprops.color': 'C2',
          'boxplot.meanprops.linestyle': '--',
          'boxplot.meanprops.linewidth': 1.0,
          'boxplot.meanprops.marker': '^',
          'boxplot.meanprops.markeredgecolor': 'C2',
          'boxplot.meanprops.markerfacecolor': 'C2',
          'boxplot.meanprops.markersize': 6.0,
          'boxplot.medianprops.color': 'C1',
          'boxplot.medianprops.linestyle': '-',
          'boxplot.medianprops.linewidth': 1.0,
          'boxplot.notch': False,
          'boxplot.patchartist': False,
          'boxplot.showbox': True,
          'boxplot.showcaps': True,
          'boxplot.showfliers': True,
          'boxplot.showmeans': False,
          'boxplot.vertical': True,
          'boxplot.whiskerprops.color': 'white',
          'boxplot.whiskerprops.linestyle': '-',
          'boxplot.whiskerprops.linewidth': 1.0,
          'boxplot.whiskers': 1.5,
          'contour.algorithm': 'mpl2014',
          'contour.corner_mask': True,
          'contour.linewidth': None,
          'contour.negative_linestyle': 'dashed',
          'date.autoformatter.day': '%Y-%m-%d',
          'date.autoformatter.hour': '%m-%d %H',
          'date.autoformatter.microsecond': '%M:%S.%f',
          'date.autoformatter.minute': '%d %H:%M',
          'date.autoformatter.month': '%Y-%m',
          'date.autoformatter.second': '%H:%M:%S',
          'date.autoformatter.year': '%Y',
          'date.converter': 'auto',
          'date.epoch': '1970-01-01T00:00:00',
          'date.interval_multiples': True,
          'docstring.hardcopy': False,
          'errorbar.capsize': 0.0,
          'figure.autolayout': False,
          'figure.constrained_layout.h_pad': 0.04167,
          'figure.constrained_layout.hspace': 0.02,
          'figure.constrained_layout.use': False,
          'figure.constrained_layout.w_pad': 0.04167,
          'figure.constrained_layout.wspace': 0.02,
          'figure.dpi': 100.0,
          'figure.edgecolor': 'black',
          'figure.facecolor': 'black',
          'figure.figsize': [8.0, 5.5],
          'figure.frameon': True,
          'figure.hooks': [],
          'figure.labelsize': 'large',
          'figure.labelweight': 'normal',
          'figure.max_open_warning': 20,
          'figure.raise_window': True,
          'figure.subplot.bottom': 0.11,
          'figure.subplot.hspace': 0.2,
          'figure.subplot.left': 0.125,
          'figure.subplot.right': 0.9,
          'figure.subplot.top': 0.88,
          'figure.subplot.wspace': 0.2,
          'figure.titlesize': 'large',
          'figure.titleweight': 'normal',
          'font.cursive': ['Apple Chancery',
                           'Textile',
                           'Zapf Chancery',
                           'Sand',
                           'Script MT',
                           'Felipa',
                           'Comic Neue',
                           'Comic Sans MS',
                           'cursive'],
          'font.family': ['sans-serif'],
          'font.fantasy': ['Chicago',
                           'Charcoal',
                           'Impact',
                           'Western',
                           'xkcd script',
                           'fantasy'],
          'font.monospace': ['DejaVu Sans Mono',
                             'Bitstream Vera Sans Mono',
                             'Computer Modern Typewriter',
                             'Andale Mono',
                             'Nimbus Mono L',
                             'Courier New',
                             'Courier',
                             'Fixed',
                             'Terminal',
                             'monospace'],
          'font.sans-serif': ['Arial',
                              'Liberation Sans',
                              'DejaVu Sans',
                              'Bitstream Vera Sans',
                              'sans-serif'],
          'font.serif': ['DejaVu Serif',
                         'Bitstream Vera Serif',
                         'Computer Modern Roman',
                         'New Century Schoolbook',
                         'Century Schoolbook L',
                         'Utopia',
                         'ITC Bookman',
                         'Bookman',
                         'Nimbus Roman No9 L',
                         'Times New Roman',
                         'Times',
                         'Palatino',
                         'Charter',
                         'serif'],
          'font.size': 10.0,
          'font.stretch': 'normal',
          'font.style': 'normal',
          'font.variant': 'normal',
          'font.weight': 'normal',
          'grid.alpha': 1.0,
          'grid.color': 'white',
          'grid.linestyle': '-',
          'grid.linewidth': 1.0,
          'hatch.color': 'black',
          'hatch.linewidth': 1.0,
          'hist.bins': 10,
          'image.aspect': 'equal',
          'image.cmap': 'gray',
          'image.composite_image': True,
          'image.interpolation': 'auto',
          'image.interpolation_stage': 'auto',
          'image.lut': 256,
          'image.origin': 'upper',
          'image.resample': True,
          'interactive': True,
          'keymap.back': ['left', 'c', 'backspace', 'MouseButton.BACK'],
          'keymap.copy': ['ctrl+c', 'cmd+c'],
          'keymap.forward': ['right', 'v', 'MouseButton.FORWARD'],
          'keymap.fullscreen': ['f', 'ctrl+f'],
          'keymap.grid': ['g'],
          'keymap.grid_minor': ['G'],
          'keymap.help': ['f1'],
          'keymap.home': ['h', 'r', 'home'],
          'keymap.pan': ['p'],
          'keymap.quit': ['ctrl+w', 'cmd+w', 'q'],
          'keymap.quit_all': [],
          'keymap.save': ['s', 'ctrl+s'],
          'keymap.xscale': ['k', 'L'],
          'keymap.yscale': ['l'],
          'keymap.zoom': ['o'],
          'legend.borderaxespad': 0.5,
          'legend.borderpad': 0.4,
          'legend.columnspacing': 2.0,
          'legend.edgecolor': '0.8',
          'legend.facecolor': 'inherit',
          'legend.fancybox': True,
          'legend.fontsize': 10.0,
          'legend.framealpha': 0.8,
          'legend.frameon': False,
          'legend.handleheight': 0.7,
          'legend.handlelength': 2.0,
          'legend.handletextpad': 0.8,
          'legend.labelcolor': 'None',
          'legend.labelspacing': 0.5,
          'legend.loc': 'best',
          'legend.markerscale': 1.0,
          'legend.numpoints': 1,
          'legend.scatterpoints': 1,
          'legend.shadow': False,
          'legend.title_fontsize': None,
          'lines.antialiased': True,
          'lines.color': 'white',
          'lines.dash_capstyle': <CapStyle.butt: 'butt'>,
          'lines.dash_joinstyle': <JoinStyle.round: 'round'>,
          'lines.dashdot_pattern': [6.4, 1.6, 1.0, 1.6],
          'lines.dashed_pattern': [3.7, 1.6],
          'lines.dotted_pattern': [1.0, 1.65],
          'lines.linestyle': '-',
          'lines.linewidth': 1.75,
          'lines.marker': 'None',
          'lines.markeredgecolor': 'auto',
          'lines.markeredgewidth': 0.0,
          'lines.markerfacecolor': 'auto',
          'lines.markersize': 7.0,
          'lines.scale_dashes': True,
          'lines.solid_capstyle': <CapStyle.round: 'round'>,
          'lines.solid_joinstyle': <JoinStyle.round: 'round'>,
          'macosx.window_mode': 'system',
          'markers.fillstyle': 'full',
          'mathtext.bf': 'sans:bold',
          'mathtext.bfit': 'sans:italic:bold',
          'mathtext.cal': 'cursive',
          'mathtext.default': 'it',
          'mathtext.fallback': 'cm',
          'mathtext.fontset': 'dejavusans',
          'mathtext.it': 'sans:italic',
          'mathtext.rm': 'sans',
          'mathtext.sf': 'sans',
          'mathtext.tt': 'monospace',
          'patch.antialiased': True,
          'patch.edgecolor': 'white',
          'patch.facecolor': '#348ABD',
          'patch.force_edgecolor': False,
          'patch.linewidth': 0.5,
          'path.effects': [],
          'path.simplify': True,
          'path.simplify_threshold': 0.111111111111,
          'path.sketch': None,
          'path.snap': True,
          'pcolor.shading': 'auto',
          'pcolormesh.snap': True,
          'pdf.compression': 6,
          'pdf.fonttype': 3,
          'pdf.inheritcolor': False,
          'pdf.use14corefonts': False,
          'pgf.preamble': '',
          'pgf.rcfonts': True,
          'pgf.texsystem': 'xelatex',
          'polaraxes.grid': True,
          'ps.distiller.res': 6000,
          'ps.fonttype': 3,
          'ps.papersize': 'letter',
          'ps.useafm': False,
          'ps.usedistiller': None,
          'savefig.bbox': None,
          'savefig.directory': '~',
          'savefig.dpi': 'figure',
          'savefig.edgecolor': 'white',
          'savefig.facecolor': 'white',
          'savefig.format': 'png',
          'savefig.orientation': 'portrait',
          'savefig.pad_inches': 0.1,
          'savefig.transparent': False,
          'scatter.edgecolors': 'face',
          'scatter.marker': 'o',
          'svg.fonttype': 'path',
          'svg.hashsalt': None,
          'svg.id': None,
          'svg.image_inline': True,
          'text.antialiased': True,
          'text.color': 'white',
          'text.hinting': 'force_autohint',
          'text.hinting_factor': 8,
          'text.kerning_factor': 0,
          'text.latex.preamble': '',
          'text.parse_math': True,
          'text.usetex': False,
          'timezone': 'UTC',
          'tk.window_focus': False,
          'toolbar': 'toolbar2',
          'webagg.address': '127.0.0.1',
          'webagg.open_in_browser': True,
          'webagg.port': 8988,
          'webagg.port_retries': 50,
          'xaxis.labellocation': 'center',
          'xtick.alignment': 'center',
          'xtick.bottom': True,
          'xtick.color': 'white',
          'xtick.direction': 'out',
          'xtick.labelbottom': True,
          'xtick.labelcolor': 'inherit',
          'xtick.labelsize': 10.0,
          'xtick.labeltop': False,
          'xtick.major.bottom': True,
          'xtick.major.pad': 7.0,
          'xtick.major.size': 0.0,
          'xtick.major.top': True,
          'xtick.major.width': 1.0,
          'xtick.minor.bottom': True,
          'xtick.minor.ndivs': 'auto',
          'xtick.minor.pad': 3.4,
          'xtick.minor.size': 0.0,
          'xtick.minor.top': True,
          'xtick.minor.visible': False,
          'xtick.minor.width': 0.5,
          'xtick.top': False,
          'yaxis.labellocation': 'center',
          'ytick.alignment': 'center_baseline',
          'ytick.color': 'white',
          'ytick.direction': 'out',
          'ytick.labelcolor': 'inherit',
          'ytick.labelleft': True,
          'ytick.labelright': False,
          'ytick.labelsize': 10.0,
          'ytick.left': True,
          'ytick.major.left': True,
          'ytick.major.pad': 7.0,
          'ytick.major.right': True,
          'ytick.major.size': 0.0,
          'ytick.major.width': 1.0,
          'ytick.minor.left': True,
          'ytick.minor.ndivs': 'auto',
          'ytick.minor.pad': 3.4,
          'ytick.minor.right': True,
          'ytick.minor.size': 0.0,
          'ytick.minor.visible': False,
          'ytick.minor.width': 0.5,
          'ytick.right': False}))

Il existe de nombreux paramètres que vous pourriez définir pour vos feuilles de style.

Définissez les paramètres de votre feuille de style en :

  1. créant votre propre fichier matplotlibrc, ou

  2. mettant à jour les valeurs stockées dans la variable de type dictionnaire plt.rcParams

Changeons le style de nos lignes de densité superposées en utilisant la seconde méthode

from cycler import cycler

# revenir à la feuille de style par défaut
plt.style.use('default')

# Vous pouvez mettre à jour des valeurs individuelles à l'aide des clés :

# Définir le style de police en italique
plt.rcParams['font.style'] = 'italic'

# Mettre à jour la largeur de ligne
plt.rcParams['lines.linewidth'] = 2


# Vous pouvez également mettre à jour plusieurs valeurs à la fois avec la méthode update() :

parameters = {

    # Modifier la taille de figure par défaut
    'figure.figsize': (5, 4),

    # Ajouter des lignes de grille horizontales
    'axes.grid': True,
    'axes.grid.axis': 'y',

    # Mettre à jour les couleurs des lignes de densité
    'axes.prop_cycle': cycler('color', 
                            ['dimgray', 'slategrey', 'darkgray'])
}

plt.rcParams.update(parameters)

Note

Ces réglages sont globaux.

Tout graphique généré après avoir modifié les paramètres dans .rcParams sera affecté par ce réglage.

fig, ax = plt.subplots()
x = np.linspace(-4, 4, 150)
for i in range(3):
    m, s = uniform(-1, 1), uniform(1, 2)
    y = norm.pdf(x, loc=m, scale=s)
    current_label = rf'$\mu = {m:.2}$'
    ax.plot(x, y, linewidth=2, alpha=0.6, label=current_label)
ax.legend()
plt.show()
_images/5368807fbbc5119c8ba7f25e045e6425c050077f5408c3876479888e3a382121.png

Appliquez à nouveau la feuille de style default pour revenir au style par défaut

plt.style.use('default')

# Réinitialiser la taille de figure par défaut
plt.rcParams['figure.figsize'] = (10, 6)

11.4. Pour aller plus loin#

  • La galerie Matplotlib propose de nombreux exemples.

  • Un excellent tutoriel Matplotlib de Nicolas Rougier, Mike Muller et Gael Varoquaux.

  • mpltools permet de basculer facilement entre les styles de tracé.

  • Seaborn facilite les graphiques statistiques courants dans Matplotlib.

11.5. Exercices#

Exercice 11.1

Tracez la fonction

\[ f(x) = \cos(\pi \theta x) \exp(-x) \]

sur l’intervalle \([0, 5]\) pour chaque \(\theta\) dans np.linspace(0, 2, 10).

Placez toutes les courbes dans la même figure.

Le résultat devrait ressembler à ceci

_images/matplotlib_ex1.png