Numpy et Matplotlib: deux librairies Python pour le calcul

publicité
Numpy et Matplotlib: deux librairies Python pour le calcul numérique
31 janvier 2016
Python possède des librairies dédiées au calcul numérique. Nous proposons de découvrir Numpy et Matplotlib.
1
Un nouvelle classe d’objets : les tableaux «numpy»
• Introduction
Pour représenter des listes de nombres ou des matrices, nous avons utilisé jusqu’à présent les «listes»
Python, par exemple t = [5, 2, 4, 1]. Nous pouvons ajouter des nombres à ces listes avec la méthode
append (par exemple, après avoir exécuté t.append(8), la liste t vaut alors [5, 2, 4, 1, 8]. De plus,
les listes Python peuvent contenir des éléments de types différents, par exemple [4, 3.1, ’cou’] contient
un entier, un flottant et une chaîne de caractères. Cette souplesse permise par Python est appréciable dans
bien des situations, mais elle ne permet pas des calculs numériques efficaces.
La librairie numpy (provient de «numeric» et «Python») propose des tableaux de type ndarray que nous
appelerons tableaux «numpy» adaptés au calcul numérique.
Il faut au prélable importer la librairie numpy, l’usage étant de la rebaptiser np.
>>> import numpy as np
On crée un tableau «numpy» avec la fonction np.array (en anglais «array» signifie tableau).
>>> t = np.array([5, 2, 4, 1])
>>> print(type(t))
<class ’numpy.ndarray’>
Le type renvoyé est ndarray qui signifie «n-dimensional array», c’est-à-dire «tableau à n dimensions». Ici
t ne possède qu’une dimension. Une matrice sera un tableau à deux dimensions. Par exemple
In : A = np.array([[1 , 2, 3], [4, 5, 6]]) # crée une matrice à deux lignes et trois colonnes
In: print(A)
Out :
array([[1, 2, 3],
[4, 5, 6]])
In : A.ndim
# donne la dimension du tableau A
Out: 2
Remarque : une image numérique RGB sera codée par une «matrice de pixels» dont le coefficient d’indice
(i, j) est un triplet de nombres (r, g, b) définissant l’intensité en rouge, vert et bleue du pixel en position
(i, j) . Cela pourra être représenté par un tableau numpy à 3 dimensions.
• Accès aux éléments : comme avec les listes. Par exemple, t[0] vaut 5 et A[0][1] vaut 2.
Le slicing fonctionne aussi. Par exemple, t[ : 2] renvoie [5,2] les deux premiers éléments de t.
Signalons que des syntaxes particulières sont permises : par exemple A[0,1] correspond à A[0][1] et
l’instruction t[ 1, : ] renverra toute la ligne de A d’indice 1 donc [4, 5, 6].
• On obtient le format du tableau avec la méthode shape qui renvoie un tuple :
1
In :
Out:
In :
Out:
t.shape
(4,) # 4 lignes (donc un vecteur colonne)
A.shape
(2, 3) # 2 lignes et 3 colonnes
Remarque : si l’on ne connaît pas shape, on peut s’en sortir avec la fonction len
In :
Out:
In :
Out:
In :
Out:
len(t)
4
len(A) # nombre de lignes
2
len(A[0]) # nombre de colonnes
3
• Objet mutable : on modifie les éléments comme pour les listes.
In : t[0] = 9
In : t
Out: array([9, 2, 4, 1])
• Attention aux copies. Comme tout objet mutable en Python, l’affectation t2 = t ne va pas réaliser une
copie de t.
t
Out:
In :
In :
In :
Out:
array([5, 3, 4, 1])
t2 = t
t2[0] = 7
t
array([7, 3, 4, 1] # contamination de t)
Les variables t et t2 sont deux étiquettes d’un même objet (on dit qu’elles pointent vers le même objet).
On utilisera copy.deepcopy pour faire des copies «profondes» de tableau.
• Première différence fondamentale avec les listes : les éléments d’un tableau «numpy» ont nécessairement
le même type.
Par exemple, l’instruction
for x in t:
print(type(x))
affiche quatre fois <class ’numpy.int32’>. Les éléments de t sont des entiers relatifs codés sur 32 bits.
Si l’on affecte un flottant à ce tableau, il sera converti en «entier 32 bits».
In : t[0] = 5.3
In : t
Out: array([5, 2, 4, 1])
On peut choisir le type des données avec l’argument dtype. Par exemple, np.array([2,1,3], dtype
= ’uint8’) est un tableau dont les éléments sont des entiers naturels codés sur 8 bits (uint signifie
«unsigned integer»).
Attention aux dépassements de capacité dans ce cas :
In : A = np.array([254 , 255, 3], dtype = ’uint8’)
In : A+1 # C on ajoute 1 à tous les coefficients du tableau
Out: array([255,
0,
4], dtype=uint8)
2
Le plus grand entier naturel représenté sur 8 bits est bien 28 − 1 = 257.
Out: B= array([126, 127,
In: B+1
Out: array([ 127, -128,
1], dtype=int8)
2], dtype=int8)
Le plus grand entier relatif représenté sur 8 bits est bien 27 − 1 = 127.
• Deuxième différence fondamentale avec les listes : les tableaux numpy ont une longueur fixée. En particulier, on ne peut pas ajouter d’éléments.
In : t.append(5)
--------------------------------------------------------------------------AttributeError
Traceback (most recent call last)
<ipython-input-67-9262fbb92a36> in <module>()
----> 1 t.append(5)
AttributeError: ’numpy.ndarray’ object has no attribute ’append’
• Quelques fonctions utiles
Les fonctions np.arange et np.linspace :
In : np.arange(1,11) # les entiers de 1 à 10
Out: array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
In :np.linspace(0,1,5) # 5 valeurs uniformément distribuées entre 0 et 1
Out: array([ 0. , 0.25, 0.5 , 0.75, 1. ])
La fonction np.zeros pour créeer des tableaux de zéros.
In : np.zeros((3,2))
Out :
array([[ 0., 0.],
[ 0., 0.],
[ 0., 0.]])
• Les tableaux numpy sont adaptés à la «vectorisation des calculs» (comportement par défaut dans les
logiciels de calcul numériques comme Scilab).
Les opérations arithmétiques se font coefficients par coefficients.
In :
Out:
In :
Out:
In :
Out:
In :
Out:
t
array([5, 3, 4, 1])
t+1
array([6, 4, 5, 2])
t + t # ce n’est pas de la concaténation
array([10, 6, 8, 2])
t * t # ce n’est pas le produit matriciel
array([25, 9, 16, 1])
On parle aussi de «mapage» :
In :
Out:
In :
Out:
np.sin(t) # applique sinus à tous les coefficients de t
array([-0.95892427, 0.14112001, -0.7568025 , 0.84147098])
np.sum(t) # somme des éléments de t
13
Remarque : la vectorisation des calculs évite l’utilisation de boucles et permet un gain de rapidité considérable.
3
4.0
3.5
3.5
3.0
3.0
mes ordonnées
4.0
2.5
2.0
1.5
1.0
1.0
courbe d'équation y = f(x)
2.5
2.0
1.5
0.5
0.0
0.5
1.0
1.5
1.0
1.0
2.0
0.5
0.0
0.5
mes abscisses
1.0
1.5
2.0
Figure 1 – Ma première ligne brisée
2
Découverte de la librairie matplotlib.pyplot
On pourra au besoin consulter ce tutoriel en français : http://matplotlib.free.fr. Le principe est simple :
on crée une liste d’abcisses, une liste d’ordonnées et on demande de tracer les points de coordonnées correspondantes. Par défaut, les points tracés sont reliés par des segments de droite, ce qui donne une courbe. On peut
demander aussi à ce que les points ne soients pas reliés, on obtient un nuage de points.
Par exemple, en exécutant le script suivant, on obtient un premier graphique.
import matplotlib.pyplot as plt
X = [-1, 0, 1, 2] # la liste des abscisses
Y = [3, 2, 4, 1] # la liste des ordonnées
plt.plot(X, Y) # pour créer le graphique
plt.show() # pour afficher le graphique
Si l’on insère les commandes suivantes, on complète le premier graphique.
plt.grid() # pour créer une grille
plt.xlabel("mes abscisses")
plt.ylabel("mes ordonnées")
plt.title("courbe d’équation $y =f(x)$")
Pour tracer une courbe, il suffira donc de placer un «grand» nombre de points.
Nous vous proposons de découvrir d’autres fonctionnalités en TD, citons par exemple :
• remplacer la ligne plt.plot(X, Y) par plt.plot(X, Y,’g-’). Dans le troisième argument de la fonction
plot, le b signifie blue et donc code la couleur et le tiret - représente le style de la courbe. On peut utiliser
les différents styles ce courbes suivants : [’-’, ’–’, ’-.’, ’:’]
• Pour créer un nuage de points : remplacer la ligne plt.plot(X, Y) par plt.plot(X, Y,’r.’). Dans
le troisième argument de la fonction plot, le r signifie red et donc code la couleur et le point . représente
le marqueur de points.
On peut utiliser les différents marqueurs de points suivants : marqueurs = [’o’, ’+’, ’.’, ’x’, ’*’]
Pour terminer, illustrons ce texte par le tracé du cercle trigonométrique. Pour cela, on trace «beaucoup» de
points de coordonnées (cos t, sin t) avec t décrivant [0, 2π].
Apprécions l’utilisation de la «vectorialisation» :
4
1.0
0.5
0.0
0.5
1.0
1.0
0.5
0.0
0.5
1.0
Figure 2 – Mon premier cercle
T = np.linspace(0,2*np.pi,200) # mes 200 abscisses entre 0 et 2pi
Xdisk = np.cos(T) # vectorisation, on applique cos au tableau numpy
Ydisk = np.sin(T)
plt.plot(Xdisk,Ydisk, ’b’)
plt.show()
5
Téléchargement