Introduction à la bibliothèque numpy
¶
Cette introduction s'inspire d'un cours de physique numérique de l'Ecole Polytechnique. Un grand merci à son auteur Michel Ferrero (CPHT, Ecole Polytechnique) pour son autorisation.
Comme vous l'avez vu dans le cours d'introduction au langage python
, les listes sont un moyen pratique
pour rassembler des données de divers types. En tant que mécanicien, vous aurez très souvent envie de travailler avec des vecteurs et des matrices. Il pourrait être tentant d'utiliser des listes pour le faire. Par exemple, vous pourriez très bien définir un vecteur v = [1,2,3]
et accéder à son deuxième élément avec, par exemple,v[1]
Toutefois, si les listes sont des objets très génériques, elles présentent certaines limites. Par exemple, elles ne se comportent pas comme on pourrait s'y attendre pour un vecteur. Pour s'en rendre compte, essayez d'exécuter le code ci-dessous et voyez si vous pouvez anticiper le résultat
# Quel est le résultat de cette opération?
print([1, 2, 3] + [2, 0, 1])
# Vous pensez obtenir [3,2,4]?
# Et pour cette opération ?
print(2 * [1, 2, 3])
Comme vous le voyez, les listes ne se comportent pas comme des vecteurs. La raison vient de ce que les listes peuvent contenir des types différents. Vous pouvez
créer une liste [1, "a",3.2]
. Que signifierait une multiplication par 2 dans ce cas ?
Enfin, en raison de cette flexibilité, certaines opérations sur les listes sont assez lentes.
Pour surmonter ces limitations, il existe une bibliothèque très utile appelée numpy
(pour num
eric py
thon en anglais) qui permet de faire des tableaux multidimensionnels. Les tableaux peuvent être utilisés pour créer des vecteurs et des matrices. Comme nous le verrons,
La bibliothèque numpy
dispose également d'outils pour effectuer des opérations mathématiques sur des tableaux en une seule commande.
Pour utiliser numpy
, vous devez d'abord l'importer. En général, en l'important, vous donnez à numpy
le nom d'alias np
:
import numpy as np
Créez vos premiers tableaux¶
Ci-dessous, nous montrons comment créer des tableaux avec des exemples.
a = np.array([1, 2, 3]) # crée un tableau à partir d'une liste
b = np.zeros(3) # un tableau rempli de zéros (1-dimension)
c = np.zeros((2, 3)) # une matrice pleine de zéros (2-dimension)
d = np.zeros((2, 3), dtype=complex) # par défaut un tableau contient des floats mais cela peut être changé
e = np.ones((3,3)) # Matrice 3x3 remplie de 1.
print("a =", a)
print("b =", b)
print("c =\n", c)
print("d =\n", d)
print("Dimensions de d:", d.shape) # afin de connaître les dimensions du tableau
Autres méthodes communes pour créer des tableaux¶
Pour éviter d'avoir à créer des tableaux manuellement, les fonctions arange
et linspace
peuvent être utiles.
np.arange(start,stop,pas)
a un fonctionnement similaire àrange
. Les deux différences sont quearange
génére un tableau numpy et le pas peut être un 'float'. Comme pour range start est inclus mais stop est exclu.np.linspace(start,stop,N)
génère N valeurs entre start et stop. Les valeurs start et stop sont inclus.
# Créer une suite de nombres (comme la commande python range)
a = np.arange(5, 6, 0.1) # comme pour range cette série s'arrête avant 6 donc ici 5.9
print("a =",a)
# Créer un intervalle de points discrétisés
b = np.linspace(1, 2, 5) # start, stop, nombre de points
print(b)
# Il est possible de récupérer le pas (step en anglais) en ajoutant un argument
c, pas = np.linspace(1, 2, 5, retstep=True)
print("pas = ", pas)
Indices et sections de tableaux¶
Vous pouvez :
- accéder à un élément d'un tableau avec les crochets
[ ]
et éventuellement les virgules,
si le tableau a de multiples dimensions. - accéder à plusieurs éléments : avec les crochets
[ ]
, les virgules,
et les:
Remarque : comme pour une liste, l'indice commence à 0 pour les tableaux numpy
.
a = np.random.randint(10, size=(3,3)) # matrice aléatoire 3x3 d'entiers de 0 à 9
print(a)
# Indices
print(a[0, 0]) # Voici le premier élément de la matrice
print(a[1, 2]) # deuxième ligne, troisième colonne
# Sections
print(a[0, :]) # Ceci est la première ligne
print(a[:, 1]) # Ceci est la deuxième colonne
print(a[0:2, 0:2]) # Ceci est le coin en haut à gauche 2x2
b = a[0:2, :] # Ceci est la section supérieure 2x3
b[0, 1] = 2 # b est une section de a, si a est modifié b le sera aussi!
print(a)
PRUDENCE : Observez le dernier exemple avec la commande b = a[0:2, :]
. En utilisant le signe =, vous ne dupliquez pas le tableau original. Le tableau b est simplement associé à la partie supérieure 2x3 du tableau a ! Si vous modifiez le tableau b, le tableau a sera également modifié !
C'est une possibilité intéressante car cela n'introduit pas de copie inutile des données mais comme ce comportement est différent d'autres langages, il peut être source d'erreurs. Nous verrons comme procéder pour faire une vraie copie (c-à-d une duplication en mémoire).
Opérations standard avec les tableaux numpy¶
La règle est que lorsque vous écrivez une opération sur un tableau, elle s'applique sur tous les éléments du tableau. Il en est de même pour des opérations entre deux tableaux de même dimensions. Nous utiliserons beaucoup cette possibilité pour éviter d'écrire des boucles.
a = np.arange(7) # Je crée un tableau
print(a)
print(a**2) # Je mets au carré tous les éléments du tableau
print(2 * a) # Je multiple par 2 tous les éléments du tableau.
a = np.array([1, 2, 3])
b = np.array([2, 1, 4])
print("a+b =",a + b)
print("a*b =",a * b)
Application d'une fonction sur un tableau¶
Les opérations standard ci-dessus agissent sur tous les éléments d'un tableau. Bien entendu, on peut aussi
vouloir le faire avec des fonctions, comme par exemple cos
. Si vous utilisez la fonction cosinus math.cos()
qui est fournie dans la bibliothèque math
de la bibliothèque standard de python
, elle n'est pas prévue pour agir sur un tableau numpy. Pour cette raison, il faut utiliser les fonctions mathématiques incluses dans le module numpy
. Pour cosinus, il faut utiliser np.cos()
.
a = np.linspace(0, 2*np.pi, 10) # remarquez que np.pi donne la constante pi
b = np.cos(a) # renvoie dans b un tableau avec les valeurs de cos(a)
print(b)
Copie de tableaux : une erreur courante¶
Lorsque vous voulez copier un tableau, veillez à utiliser .copy()
comme dans cet exemple :
a = np.array([1,2,3])
b = a.copy()
En effet, vous pourriez avoir des surprise!. Vérifiez la sortie de ce code :
a = np.array([1, 2, 3])
print("original de a: ", a)
b = a # Cette commande associe b et a
b[0] = 4 # Comme b est le même que a cette ligne modifie a aussi
print("a est modifié: ", a)
b = a.copy()
b[0] = 12
print("a est inchangé: ", a) # car b est indépendant de a
print("b est changé: ", b)
Produit scalaire et produit matriciel¶
Comme déjà vu, pour deux vecteurs ou deux matrices
de même taille en écrivant a * b
, le résultat correspond à une multiplication éléments par éléments.
Si vous voulez plutôt faire un produit scalaire ou une multiplication matricielle,
vous devez l'écrire avec @
:
a = np.array([1, 2, 3])
b = np.array([2, 1, 1])
print("produit scalaire de a et b = ", a@b)
a = np.array([[1, 2], [2, 3]])
b = np.array([[1, 1], [2, 2]])
print("produit matriciel = \n", a@b)
# Si vous utilisez Python version 3.4 ou inférieur, le symbole `@` ne peut pas être utilisé pour la multiplication des matrices
# a @ b -> np.dot(a, b)
# c = np.array([[4, 7], [-10, 15]])
# a @ b @ c -> a.dot(b).dot(c)
Algèbre linéaire¶
Dans numpy, on peut utiliser une bibliothèque d'algèbre linéaire. numpy.linalg
pour :
- Résoudre des systèmes linéaires
numpy.linalg.solve()
- Calculer le determinant
numpy.linalg.det()
, les valeurs propres d'une matricenumpy.linalg.eigvals()
Par exemple si on cherche à résoudre le système $Ax = b$ suivant :
$$ \left( {\begin{array}{cc} 1 & 2 \\ 3 & 5 \\ \end{array} } \right) \left( {\begin{array}{c} x_0 \\ x_1 \\ \end{array} } \right) = \left( {\begin{array}{c} 1 \\ 2 \\ \end{array} }\right) $$ les commandes sont :
import numpy as np
A = np.array([[1, 2], [3, 5]])
b = np.array([1, 2])
x = np.linalg.solve(A, b)
print(x)
Lecture et écriture dans un fichier avec numpy¶
Un exemple basique :
tabTest = np.linspace (0,1,9) # créer un tableau numpy : [0. 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1.]
# Ecriture de tabTest dans le fichier monFichier.dat
np.savetxt('monFichier.dat',tabTest)
#Lecture dans un fichier:
mesdata = np.loadtxt('monFichier.dat') # charge les données du fichier monFichier.dat dans le tableau mesdata
Les fichiers ont parfois plusieurs colonnes avec des délimiteurs qui ne sont pas nécessairement un espace (délimiteur par défaut). Il arrive que les premières lignes soient un entête pour décrire les données. Enfin, si on connait à l'avance le nombre de colonnes, on peut vouloir assigner directement un nom de variable à une colonne. Il y a pour tout cela quelques options utiles :
- Pour lire/écrire sur plusieurs colonnes indiquer/utiliser un délimiteur (espace, virgule, point virgule ...):
mesdata = np.loadtxt('monFichier.dat',delimiter=',')
np.savetxt('monFichier.dat',tab2Col,delimiter=',')
- Pour sauter un entête (premières lignes d'un fichier) utiliser skiprows
mesdata = np.loadtxt('monFichier.dat',skiprows=3,delimiter=',') # saute trois lignes
- Pour assigner chaque colonne directement à une variable, utiliser unpack
temps,vitesse = np.loadtxt('Mavitesse.dat',unpack=True)
Demander de l'aide¶
Dans spyder
, l'aide sur une fonction numpy
(ou matplotlib.pyplot
) s'obtient en selectionnant une fonction et la séquence de touches CTRL+i (i comme information)