Site icon AranaCorp

Créer des graphiques avec Matplotlib sous Python

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

timemyData
032.0
146.2
22490
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

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

#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.

## 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

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

Sources

Quitter la version mobile