Le paquet Python Matplotlib est un outil puissant pour créer des graphiques et analyser des données sous forme de graphique. Nous allons voir dans ce tutoriel comment utiliser cette librairie et certaines fonctionnalités à connaitre
Installation de Matplotlib
La librairie Matplotlib s’installe comme tous paquets Python
python -m pip install matplotlib
Pour manipuler les données, il est possible d’utiliser Numpy et Panda
python -m pip install numpy pandas
Récupérer des données à tracer
Il est possible de récupérer des données à partir de fichier CSV avec Pandas
time | myData |
0 | 32.0 |
1 | 46.2 |
2 | 2490 |
… | … |
10 | -2,45 |
import pandas as pd df = pd.read_csv(filename,sep=";",encoding = "ISO-8859-1",header=1) mydata = df["myData"]
Il est aussi possible de traité les données créé par votre programme avec Numpy
import numpy as np ylist=[] x = np.linspace(0, 10, 1000) for i in range(8): y = np.random.randn(1)*np.sin((i+1)*np.random.randn(1)*x) # + 0.8 * np.random.randn(50) ylist.append(y)
Nous allons utiliser cette dernière méthode pour tracer des courbes
Tracer une simple figure
Pour tracer une courbe, nous créons d’abord une fenêtre (figure), puis nous créons une courbe (plot)
import matplotlib.pyplot as plt import numpy as np import pandas as pd #plt.close('all') #close all figure #process data ylist=[] x = np.linspace(0, 10, 1000) for i in range(8): y = np.random.randn(1)*np.sin((i+1)*np.random.randn(1)*x) ylist.append(y) #single plot fig = plt.figure() plt.plot(x, y) # plot(y) #mutliple plots fig = plt.figure() for y in ylist: plt.plot(x, y)
Le plot s’affiche sur la figure active, pour rendre une figure active vous pouvez leur donner des noms ou des numéros ou vous souvenir de l’ordre dans lequel elles sont créees.
fig1 = plt.figure(1) fig2 = plt.figure(2) fig3 = plt.figure("myData") # use fig2 plt.figure(1) # make fig1 active #use fig1
Fermer les figures
Une fois que vous aviez fait ce que vous souhaitiez avec la figure, vous pouvez la fermer avec la commande plt.close()
plt.close() #close active figure plt.close(1) # plot first created figure or figure 1 plt.close("myData") #plot figure named myData plt.close('all') # close all figures
N.B.: plt.close(‘all’) peut être placer en début de programme afin de fermer toutes les fenêtres précédemment ouvertes à l’exécution du programme
Sauvegarder une figure au format image
Il est possible de sauvegarder chaque image tracer à l’aide de l’icône sauvegarder de la fenêtre. Il est aussi possible de demander à pyplot de sauvegarder la figure au format PNG ou JPG
plt.savefig("myImg.jpg",bbox_inches='tight') #png no label
Personnalisation de la figure
Nous avons vu que nous pouvions donner un identifiant à la figure (plt.figure(« myData »). Il est possible de définir d’autre paramètres notamment
- la taille de la fenêtre figsize
- la couleur du fond facecolor
- spécifier un titre suptitle
pyplot.figure(num=None, figsize=None, dpi=None, *, facecolor=None, edgecolor=None, frameon=True, FigureClass=<class 'matplotlib.figure.Figure'>, clear=False, **kwargs)
#customize figure fig = plt.figure("myData",figsize=(12,4),facecolor=(0.5, 0.8, 0.3)) fig.suptitle("myFigure") plt.plot(x, y)
Personnaliser le graphique
Pour compléter la personnalisation de la figure, nous pouvons personnaliser le graphique
- le titre du graphe
- les labels des axes
- la légende et sa position
- les extremum des axes
#customize plot fig = plt.figure("myData",figsize=(12,4),facecolor=(1, 1, 1)) plt.title("myData y(x)") plt.plot(x, y, label="y(x)") plt.axis([min(x)-1, max(x)+1, min(y)*1.05, max(y)*1.05]); plt.xlabel("x [s]") plt.ylabel("y [SI]") plt.legend(loc='upper left')
Personnaliser la courbe
Comme nous l’avons vu lorsqu’on trace plusieurs courbe, Matplotlib sélectionne des styles différents pour chaque courbe. Il est possible de personnaliser les courbes de manière spécifique.
- style de ligne linestyle (ls)
- couleur de ligne color
- largeur de ligne linewidth (lw)
- style de marqueur marker
- couleur de marqueur markerfacecolor (mfc) markeredgecolor (mec)
- taille de marqueur markersize (ms)
## customize curve fig = plt.figure() plt.plot(x, y, "ko--") plt.axis([4, 4.5, min(y)*1.05, max(y)*1.05]); #plt.plot(x, y, color="k", linestyle="--", linewidth=1, marker= "o") #equivalent
#customize marker fig = plt.figure() plt.plot(x, y, marker = 'o', ms = 5, mfc = 'r', mec = 'k') plt.axis([4, 4.5, min(y)*1.05, max(y)*1.05]);
Créer une fonction pour tracer des courbes
Comme il y a un grand nombre de paramètres à définir pour tracer avec Matplotlib, je vous conseille vivement de créer une fonction de traçage qui vous simplifiera la vie et que vous pourrez adapter au besoin
# -*- coding: utf-8 -*- import matplotlib.pyplot as plt import numpy as np plt.close("all") ylist=[] ylbl = [] x = np.linspace(0, 10, 1000) for i in range(8): y = np.random.choice([-1,1])*(i+1)*np.sin((i+1)*x) ylist.append(y) ylbl.append('y{}(x)'.format(i)) ##styles options lstyles= ['-', '--', '-.', ':', 'None', ' ', '', 'solid', 'dashed', 'dashdot', 'dotted'] markers = [None,'o','*','.',',','x','X','+','P','s','D','d','p','H','h','v','^','<','>','1','2','3','4','|','_'] def tracefig(x,y,lbl,ls=None,mrkr=None,title=None,xlbl=None,ylbl=None,size=(12,4),zoomx=None,gridon=False): fig = plt.figure(figsize=size,facecolor=(1, 1, 1)) if title is not None: title = "tracefig - {}".format(title) plt.title(title) if type(y) is not list: if ls is None: ls=np.random.choice(lstyles) if mrkr is None: mrkr=np.random.choice(markers) plt.plot(x, y, linestyle=ls, marker = mrkr, label=lbl) else: for i,y in enumerate(ylist): if ls is None: ls=np.random.choice(lstyles) if mrkr is None: mrkr=np.random.choice(markers) plt.plot(x, y, linestyle=ls, marker = mrkr, label=lbl[i]) plt.xlabel(xlbl) plt.ylabel(ylbl) plt.legend(loc='upper left') if zoomx is None: plt.axis([min(x), max(x), np.min(ylist)*1.2, np.max(ylist)*1.2]); else: plt.axis([zoomx[0], zoomx[1], np.min(ylist)*1.2, np.max(ylist)*1.2]); if gridon: plt.grid() #diplay grid return fig fig = tracefig(x,y,"y(x)",ls="-",mrkr="o",title="Single plot",xlbl="x [s]",ylbl="y [SI]",size=(12,4),zoomx=[0,2]) fig = tracefig(x,ylist,ylbl,ls="-",mrkr=None,title="Multi plots",xlbl="x [s]",ylbl="y [SI]",size=(12,4),zoomx=[0,2], gridon=True)
Avec ces connaissances, vous pouvez tracer et analyser tout types de courbes à l’aide Matplotlib et Python
Afficher des nuages de points
Pour l’analyse de données, il est aussi possible d’afficher des nuages de points. Dans cet exemple, nous colorions les points en fonctions d’une troisième variable
import matplotlib.pyplot as plt import numpy as np plt.close("all") x = np.random.randn(50) y = np.random.randn(50) z = np.random.randint(1,100,50) #np.random.randn(50) value=(z>50) colors = np.where( value==True , "red", "#3498db") fig = plt.figure() plt.scatter(x,y,marker='s',color=colors) plt.show()
Tracer des histogrammes
Pour chaque données il y a une représentation judicieuse. Dans certain cas un histogramme sera plus parlant
import matplotlib.pyplot as plt import numpy as np plt.close("all") nb = 10 x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]] fig = plt.figure() plt.hist(x_multi, nb, histtype='bar', label=['d1','d2','d3']) plt.legend(prop={'size': 10}) plt.title('Histogram') plt.show()
Tracer des diagrammes circulaires
import matplotlib.pyplot as plt labels = 'Insurance', 'Workshop', 'Salary', 'Bank' sizes = [15, 30, 45, 10] explode = (0, 0.05, 0, 0) fig, ax = plt.subplots() ax.pie(sizes, explode=explode, labels=labels, autopct='%1.1f%%',colors=['olivedrab', 'rosybrown', 'gray', 'saddlebrown'],startangle=80)
Tracer des contours
Les contours sont utiles pour tracer en 2D des données 3D comme le dénivelé par exemple.
import numpy as np import matplotlib.pyplot as plt def g(x, obs = [[-2,0],[8,-5]], param = [[1000,20, 60],[500,10, 30]]): res = 200 for i in range(0,len(obs)): alpha_obstacle, a_obstacle,b_obstacle = param[i] x_obstacle , y_obstacle = obs[i] res += -alpha_obstacle * np.exp(-((x[0] - x_obstacle)**2 / a_obstacle + (x[1] - y_obstacle)**2 / b_obstacle)) return res x = np.linspace(-10, 10, 200) y = np.linspace(-10, 10, 200) X = np.meshgrid(x, y) Z = g(X) CS = plt.contour(X[0], X[1], Z) #, colors='black') plt.clabel(CS, fontsize=9, inline=True) plt.show()
Créer des planches de graphique avec Matplotlib
Pour une visualisation plus globale des données, une technique importante est de savoir tracer plusieurs graphique sur une même figure.
Utilisation des subplots
Il est possible de diviser une figure en rangée et colonnes afin d’organiser les courbes de manières plus lisible et de lier plus facilement les axes
fig = plt.figure()
ax_list = fig.subplots(row, col, sharex=True, sharey=True)
import matplotlib.pyplot as plt import numpy as np plt.close("all") ylist=[] ylbl = [] x = np.linspace(0, 10, 1000) for i in range(8): y = np.random.choice([-1,1])*(i+1)*np.sin((i+1)*x) ylist.append(y) ylbl.append('y{}(x)'.format(i)) fig2 = plt.figure(figsize=(8, 6)) fig2.suptitle("my Plots") #devide figure in 3 rows and 2 columns with shared axis (row1col1, row1col2),(row2col1, row2col2),(row3col1, row3col2) = fig2.subplots(3, 2,sharex=True,sharey=True) ax = row1col1 ax.plot(x, ylist[0], label="y1(x)") ax.set_title('Y(X)') ax = row1col2 ax.plot(x, ylist[1], label="y1(x)") ax = row2col1 ax.plot(x, ylist[2], label="y2(x)") ax = row2col2 ax.plot(x, ylist[3], label="y3(x)") ax = row3col1 ax.plot(x, ylist[4], label="y4(x)") ax = row3col2 ax.plot(x, ylist[5], label="y5(x)")
Utilisation des subfigures
Pour des disposition plus complexes, il est possible d’utiliser subfigure
fig = plt.figure(figsize=(10, 8)) (row1fig, row2fig) = fig.subfigures(2, 1, height_ratios=[1, 2]) row1fig.suptitle("Subfigure") (fig_row2left, fig_row2right) = row2fig.subfigures(1, 2) row1_ax = row1fig.add_subplot() row2l_axs = fig_row2left.subplots(2,1) row2r_ax = fig_row2right.add_subplot() ax = row1_ax ax.plot(x, ylist[0]) ax = row2l_axs[0] ax.plot(x, ylist[2],'ro-') ax = row2l_axs[1] ax.plot(x, ylist[3],'k.-') ax = row2r_ax ax.plot(ylist[4], ylist[5],'g-')
Utilisation de GridSpec
Avec GridSpec, il est possible de dessiner rapidement des agencements complexes. Plutôt que de diviser des zones successivement, nous allons définir une grille que nous allons remplir au fur et à mesure avec des sous-graphiques.
fig = plt.figure(figsize=(10, 8)) fig.suptitle("GridSpec") gs = plt.GridSpec(3, 3) gs.update(wspace=0.4, hspace=0.6) col1fig0 = fig.add_subplot(gs[0, :2]) col1fig1 = fig.add_subplot(gs[1, :2],sharex=col1fig0) col1fig2 = fig.add_subplot(gs[2, :2],sharex=col1fig0) col2fig0 = fig.add_subplot(gs[:1, 2]) col2fig1 = fig.add_subplot(gs[1:, 2]) ax=col1fig0 ax.plot(x, ylist[1], label="y1(x)") ax=col1fig1 ax.plot(x, ylist[2], 'kx-',label="y2(x)") ax=col1fig2 ax.plot(x, ylist[3], 'ro:', label="y3(x)") ax=col2fig0 ax.plot(ylist[4], ylist[5], 'g-',label="y5(y4)") ax=col2fig1 ax.plot(ylist[6],x,'s', label="y6(x)") fig.legend(loc='upper left')
N.B.: Vous pouvez combiner subfigure, subplot et gridspec et les imbriquer comme vous le souhaitez afin de réaliser vos plus beaux graphiques
Ajouter un curseur à vos graphiques
Pour un meilleur lecture, il est possible rajouter un curseur afin de visualiser certains détails plus précisément. Ce curseur peux être partagé entre plusieurs courbes. Nous pouvons, par exemple, rajouter un curseur sur les trois courbes de gauches de la figure précédentes et définir ces paramètres
- ls linestyle
- lw linewidth
- color
- horizOn tracé horizontal
- vertOn tracé vertical
from matplotlib.widgets import MultiCursor figlist = (col1fig0,col1fig1,col1fig2) cursor = MultiCursor(fig.canvas, figlist, color='r',lw=0.5, ls='--', horizOn=True,vertOn=True)
Détecter les évènements de la souris
En plus de tracer, des courbes et de les animer, il est possible d’utiliser la souris pour interagir avec le graphique
import numpy as np import matplotlib.pyplot as plt from matplotlib.backend_bases import MouseButton def on_click(event): if event.button is MouseButton.LEFT: print("Click detected at X,Y: {}".format([event.xdata, event.ydata])) fig = plt.figure() plt.plot([0,1],[0,2]) plt.connect('button_press_event', on_click) plt.show()
Créer une animation avec Matplotlib
Vous pouvez créer des graphiques animés et les enregistrer sous différents format à l’aide de l’outil matplotlib.animation. Pour cela, il faut tracer le graphique image par image dans une fonction update(frame) qui retourne l’objet contenant le graphique (ici curve).
import math import numpy as np import matplotlib.pyplot as plt import matplotlib.animation as animation #create data #process data x = np.linspace(0, 10, 100) y = np.sin(2*x) # plot first point fig = plt.figure() curve = plt.plot(x[0], y[0]) plt.axis([0, 10, -1.2, 1.2]) def update(frame): # update data xi = x[:frame] yi = y[:frame] # update plot curve[0].set_xdata(xi) curve[0].set_ydata(yi) return (curve) #display animation ani = animation.FuncAnimation(fig=fig, func=update, frames=100, interval=30) plt.show() #save animation as gif ani.save(filename="./tmp/sinewave.gif", writer="pillow")
Il existe différentes manière de créer des animation en fonction de vos types de données. Vous pouvez également enregistrer les animations sous différents formats en fonction de leur utilisation. N’hésitez pas à consulter la documentation de Animation.
Applications
- Afficher les données d’un capteur Lidar
- Afficher les images d’une caméra
- Visualiser vos algorithmes et vos données