6. TP - numpy
6.1. Introduction
Numpy pour Numerical Python est une librairie liée au calcul scientifique et qui permet de traiter efficacement les données sous forme de tableaux à une ou deux dimensions.
Pour l'utiliser il faut l'avoir installée sous Python en utilisant pip ou conda (pour la version Anaconda de Python).
Sous Ubuntu on utilise apt :
$ sudo apt install python3-numpy
On doit ensuite importer la librairie dans le fichier Python que l'on va créer afin de pouvoir en utiliser les fonctionnalités.
En général on écrit :
import numpy as np
Dès lors, il faudra préfixer toutes les fonctions de numpy par np.
Le lien suivant donne accès à la documentation.
Dans la suite de ce TP, on donne quelques exemples d'utilisation de numpy. Pour résoudre les exercices
en fin de TP, deux possibilités s'offrent à vous :
- lire et comprendre les différents morceaux de code ci-dessous, puis répondre aux exercices
- répondre aux exercices en cherchant dans le code comment faire : utilisez CTRL+F pour
rechercher des mots-clés dans la page
Notez que le tableaux / matrices créés par numpy sont de type <class 'numpy.ndarray'>
.
6.2. Tableaux à une dimension
6.2.1. Création de tableaux
6.2.1.a création à partir de liste
On peut créer un tableau en donnant sa liste de valeurs. Dans l'exemple qui suit on crée un tableau à une dimension composé de quatre valeurs, puis on affiche différents éléments du tableau ainsi que des propriétés :
import numpy as np
# definition
tableau = np.array( [10, 11, 12, 13] )
# affiche le tableau
print("tableau = ", tableau)
# affiche le premier et le second élément
print("tableau[0] = ", tableau[0])
print("tableau[1] = ", tableau[1])
print("nombre d'éléments = ", tableau.size)
print("nombre de dimensions = ", tableau.ndim)
print("dimension(s) = ", tableau.shape)
print("taille première dimension =", tableau.shape[0])
tableau = [10 11 12 13]
tableau[0] = 10
tableau[1] = 11
nombre d'éléments = 4
nombre de dimensions = 1
dimension(s) = (4,)
taille première dimension = 4
Un tableau numpy possède les propriétés suivantes :
- size qui correspond au nombre d'éléments du tableau
- ndim ou nombre de dimensions, ici il n'y en a qu'une seule
- shape qui contient les dimensions du tableau si par exemple on a créé un tableau à plusieurs dimensions, il s'agit d'une liste de valeurs
6.2.1.b tableau de 1 ou de 0
On peut créer un tableau avec les fonctions ones qui crée un tableau de 1, ou zeros qui crée un tableau de 0 :
import numpy as np
# tableau composé de 5 fois la valeur 0.0 (réel/flottant)
tableau_reels = np.zeros(5)
print(tableau_reels)
# tableau composé de 5 fois la valeur 0 (entier)
# on précise ici le type de représentation qui sera 'int'
tableau_entiers = np.zeros(5, dtype=int)
print(tableau_entiers)
# tableau de 15 entiers initialisés à 1 (entier)
tableau_entiers = np.ones(15, dtype=int)
print(tableau_entiers)
[0. 0. 0. 0. 0.]
[0 0 0 0 0]
[1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
Pour créer un tableau avec valeur initiale, on peut procéder de deux manières différentes :
- soit on crée un tableau initialisé avec des 1, puis on le multiplie par la valeur voulue
- soit on utilise la fonction full (version 1.8 de numpy)
import numpy as np
tableau_reels = np.ones(10)
tableau_reels *= 7
print(tableau_reels)
tableau_reels = np.full(10, 7.0)
print(tableau_reels)
[7. 7. 7. 7. 7. 7. 7. 7. 7. 7.]
[7. 7. 7. 7. 7. 7. 7. 7. 7. 7.]
6.2.1.c création à partir de séquence
Pour créer un tableau avec des valeurs croissantes (ou décroissantes), on utilise arange :
import numpy as np
tableau_entiers = np.arange(1,10)
print(tableau_entiers)
tableau_entiers = np.arange(1,30,3)
print(tableau_entiers)
tableau_entiers = np.arange(start = 1, stop = 30, step = 3)
print(tableau_entiers)
[1 2 3 4 5 6 7 8 9]
[ 1 4 7 10 13 16 19 22 25 28]
[ 1 4 7 10 13 16 19 22 25 28]
6.2.1.d création de tableau contenant des valeurs aléatoires
Pour créer un tableau avec des valeurs aléatoires, on utilise random :
import numpy as np
# créer un tableau de 10 valeurs comprises dans [0, 1.0[
tableau_alatoire_reels = np.random.random( 10 )
print(tableau_alatoire_reels)
# créer un tableau de 10 valeurs entières comprises
# entre -7 et 7
tableau_alatoire_entiers = np.random.randint(-7, 8, 10)
print(tableau_alatoire_entiers)
[0.12998079 0.14740233 0.08009652 0.29976755 0.74843822 0.69646599
0.93848072 0.45822846 0.56578287 0.68722764]
[ 3 -1 5 -4 -3 -6 -3 6 3 -3]
6.2.2. Modification de tableaux
6.2.2.a ajout en fin
Pour ajouter une valeur à la fin du tableau, on utilise append. Attention, cependant, car il faut réassigner le tableau modifié au tableau initial.
import numpy as np
tableau_entiers = np.array([1,2,3])
print(tableau_entiers)
# modification non prise en compte
np.append(tableau_entiers, 4)
print(tableau_entiers)
# prise en compte de la valeur en réassignant le tableau
tableau_entiers = np.append(tableau_entiers, 4)
print(tableau_entiers)
[1 2 3]
[1 2 3]
[1 2 3 4]
6.2.2.b ajout au milieu ou au début
Pour insérer une valeur on utilise insert. Attention, cependant, car il faut réassigner le tableau modifié au tableau initial.
import numpy as np
tableau_entiers = np.array([1,2,3,4,5,6])
print(tableau_entiers)
tableau_entiers = np.insert(tableau_entiers, 3, -7)
print(tableau_entiers)
tableau_entiers = np.insert(tableau_entiers, 0, -3)
print(tableau_entiers)
[1 2 3 4 5 6]
[ 1 2 3 -7 4 5 6]
[-3 1 2 3 -7 4 5 6]
6.2.2.c suppression
Pour supprimer une valeur on utilise delete. Attention, cependant, car il faut réassigner le tableau modifié au tableau initial.
import numpy as np
tableau_entiers = np.array([1,2,3,4,5,6])
print(tableau_entiers)
tableau_entiers = np.delete(tableau_entiers, 3)
print(tableau_entiers)
[1 2 3 4 5 6]
[1 2 3 5 6]
6.2.3. Recherche et extraction
Le slicing consiste à prendre une partie d'un tableau en indiquant les indices que l'on sélectionne dans une plage de valeurs :
import numpy as np
tableau_entiers = np.array([10,11,12,13,14,15,16,17,18])
print(tableau_entiers[2:5])
print(tableau_entiers[:3])
print(tableau_entiers[-2:])
[12 13 14]
[10 11 12]
[17 18]
La recherche de valeurs se fait grâce à where qui donne une liste des indices qui correspondent à un critère de recherche donné :
import numpy as np
tableau_entiers = np.array([1,2,3,4,5,6,5,6,5,3])
indices = np.where(tableau_entiers == 5)
print(indices[0])
[4 6 8]
La sélection de valeurs peut également se faire avec les formulations suivantes si on a un critère
de sélection avec plusieurs conditions à remplir :
import numpy as np
# première méthode
# condition entre crochets du tableau
tableau_entiers = np.arange(1,30,2)
print(tableau_entiers)
nouveau_tableau = tableau_entiers[(tableau_entiers > 10) & (tableau_entiers <= 15)]
print(nouveau_tableau)
# deuxième méthode
# choix des indices correspondant aux critères
selection = (tableau_entiers > 10) & (tableau_entiers <= 15)
nouveau_tableau = tableau_entiers[ selection ]
print(nouveau_tableau)
[ 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29]
[11 13 15]
[11 13 15]
6.2.4. Appliquer une fonction à un tableau
import numpy as np
# fonction à appliquer
def carre(x):
return x*x
# fonction vectorisée (qui peut s'appliquer en parallèle sur
# chacun des éléments d'un tableau)
vec_carre = np.vectorize(carre)
tableau_entiers = np.array([10,11,12,13,14,15,16,17,18])
tableau_entiers = vec_carre(tableau_entiers)
print(tableau_entiers)
[100 121 144 169 196 225 256 289 324]
6.3. Tableaux à deux dimensions (Matrices)
6.3.1. Création de tableaux
On peut créer une matrice (tableau à deux dimensions) de plusieurs manières différentes :
import numpy as np
# définition avec lignes
matrice_entiers = np.array([[11,12,13,14],[21,22,23,24]])
# ou liste de valeurs et reshape
matrice_entiers = np.array([11,12,13,14,21,22,23,24]).reshape(2,4)
print(matrice_entiers)
print(matrice_entiers.shape)
print("dimension sur y=", matrice_entiers.shape[0])
print("dimension sur x=", matrice_entiers.shape[1])
print("nombre d'éléments=", matrice_entiers.size)
print("première ligne=", matrice_entiers[0])
print("deuxième ligne=", matrice_entiers[1])
print(matrice_entiers[0][2])
[11 12 13 14]
[21 22 23 24]]
(2, 4)
dimension sur y= 2
dimension sur x= 4
nombre d'éléments= 8
première ligne= [11 12 13 14]
deuxième ligne= [21 22 23 24]
13
On peut également utiliser ones ou zeros :
import numpy as np
matrice_entiers = np.ones((5,3))
print(matrice_entiers)
print(matrice_entiers.shape)
print("dimension sur y=", matrice_entiers.shape[0])
print("dimension sur x=", matrice_entiers.shape[1])
print("nombre d'éléments=", matrice_entiers.size)
print("première ligne=", matrice_entiers[0])
print("deuxième ligne=", matrice_entiers[1])
print(matrice_entiers[0][2])
id_ligne = 0
for ligne in matrice_entiers:
print("ligne ", id_ligne, " : ", ligne)
id_ligne += 1
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
(5, 3)
dimension sur y= 5
dimension sur x= 3
nombre d'éléments= 15
première ligne= [1. 1. 1.]
deuxième ligne= [1. 1. 1.]
1.0
ligne 0 : [1. 1. 1.]
ligne 1 : [1. 1. 1.]
ligne 2 : [1. 1. 1.]
ligne 3 : [1. 1. 1.]
ligne 4 : [1. 1. 1.]
Il existe la fonction eye qui crée la matrice identité :
import numpy as np
matrice_entiers = np.eye(5)
print(matrice_entiers)
print(matrice_entiers.shape)
print("dimension sur y=", matrice_entiers.shape[0])
print("dimension sur x=", matrice_entiers.shape[1])
print("nombre d'éléments=", matrice_entiers.size)
print("première ligne=", matrice_entiers[0])
print("deuxième ligne=", matrice_entiers[1])
print(matrice_entiers[0][2])
matrice_entiers[0][2] = -777
id_ligne = 0
for ligne in matrice_entiers:
print("ligne ", id_ligne, " : ", ligne)
id_ligne += 1
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]
(5, 5)
dimension sur y= 5
dimension sur x= 5
nombre d'éléments= 25
première ligne= [1. 0. 0. 0. 0.]
deuxième ligne= [0. 1. 0. 0. 0.]
0.0
ligne 0 : [ 1. 0. -777. 0. 0.]
ligne 1 : [0. 1. 0. 0. 0.]
ligne 2 : [0. 0. 1. 0. 0.]
ligne 3 : [0. 0. 0. 1. 0.]
ligne 4 : [0. 0. 0. 0. 1.]
6.3.1.a Modification de matrices
6.3.1.b Ajouter une colonne à une matrice
import numpy as np
matrice_entiers = np.ones((5,3))
colonne = np.array([8,9,10,11,12]).reshape(5,1)
matrice_entiers = np.append(matrice_entiers, colonne, axis=1 )
print(matrice_entiers)
[[ 1. 1. 1. 8.]
[ 1. 1. 1. 9.]
[ 1. 1. 1. 10.]
[ 1. 1. 1. 11.]
[ 1. 1. 1. 12.]]
6.3.1.c Insérer une ligne dans une matrice
import numpy as np
matrice_entiers = np.ones((5,3))
colonne = np.arange(1,4)
matrice_entiers = np.insert(matrice_entiers, 1, colonne, axis=0 )
print(matrice_entiers)
[[1. 1. 1.]
[1. 2. 3.]
[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
6.3.1.d Insérer une colonne dans une matrice
import numpy as np
matrice_entiers = np.ones((5,3))
colonne = np.arange(1,6)
matrice_entiers = np.insert(matrice_entiers, 1, colonne, axis=1 )
print(matrice_entiers)
[[1. 1. 1. 1.]
[1. 2. 1. 1.]
[1. 3. 1. 1.]
[1. 4. 1. 1.]
[1. 5. 1. 1.]]
6.3.1.e Supprimer une ligne dans une matrice
import numpy as np
matrice_entiers = np.arange(1,16).reshape(5,3)
print(matrice_entiers)
matrice_entiers = np.delete(matrice_entiers, 1, axis=0)
print(matrice_entiers)
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]
[13 14 15]]
[[ 1 2 3]
[ 7 8 9]
[10 11 12]
[13 14 15]]
6.3.1.f Supprimer une colonne dans une matrice
import numpy as np
matrice_entiers = np.arange(1,16).reshape(5,3)
print(matrice_entiers)
matrice_entiers = np.delete(matrice_entiers, 1, axis=1)
print(matrice_entiers)
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]
[13 14 15]]
[[ 1 3]
[ 4 6]
[ 7 9]
[10 12]
[13 15]]
6.4. Exercices
Exercice 6.1
- générer un vecteur $X$ de valeurs dans l'intervalle [1,3[ par pas de 0.5 en utilisant numpy.arange
- générer un vecteur $Y$ de valeurs dans l'intervalle [3,1[ par pas de -0.5 en utilisant numpy.arange
- réaliser la somme des vecteurs $Z = X + Y$ puis l'afficher
- appliquer la racine carrée sur le vecteur $Z$ et afficher le résultat
X= [1. 1.5 2. 2.5]
Y= [3. 2.5 2. 1.5]
Z=X+Y= [4. 4. 4. 4.]
Z=sqrt(Z)= [2. 2. 2. 2.]
Exercice 6.2
- créer une matrice $M1$ de dimensions (3,5) avec des valeurs dans l'intervalle [1,15]
- créer une matrice $M2$ de dimensions (5,3) avec des valeurs dans l'intervalle [15,1]
- réaliser le produit $M_3 = M_1 × M_2$ puis l'afficher
- calculer la transposée $M_4 = M_3^t$ puis l'afficher
- afficher la somme des valeurs de $M_4$
M1= [[ 1 2 3 4 5]
[ 6 7 8 9 10]
[11 12 13 14 15]]
M2= [[15 14 13]
[12 11 10]
[ 9 8 7]
[ 6 5 4]
[ 3 2 1]]
M3= [[105 90 75]
[330 290 250]
[555 490 425]]
M4= [[105 330 555]
[ 90 290 490]
[ 75 250 425]]
sum = 2610
Exercice 6.3
A partir de la matrice suivante de taille (5,3), ajouter la colonne 4 composée de [1,3,5,7,9] et la colonne 5 composée de [2,4,6,8,10].
matrice_entiers = np.ones((5,3))
On veut donc obtenir :
[[ 1. 1. 1. 1. 2.]
[ 1. 1. 1. 3. 4.]
[ 1. 1. 1. 5. 6.]
[ 1. 1. 1. 7. 8.]
[ 1. 1. 1. 9. 10.]]
Exercice 6.4
- Générer un vecteur $X$ de 10 valeurs aléatoires comprises entre 1.0 et 10.0 en utilisant numpy.random.uniform
- Générer un vecteur $Y$ de booléens qui indique si $X[i]$ est compris entre 1.0 et 5.0
- Créer un vecteur $Z$ qui sélectionne les valeurs de $X$ à partir de $Y$
On veut donc obtenir :
X= [9.81902182 1.43352921 7.92413626 2.98401466 9.46288322 4.24775828
6.50744638 6.7438592 7.41775024 6.80153364]
Y= [False True False True False True False False False False]
Z= [1.43352921 2.98401466 4.24775828]
Exercice 6.5
Récupérez les données des Iris de Fisher et
créez trois matrices numpy avec les données des sépales et pétales pour chaque espèce (virginica, setosa, versicolor) :
import numpy as np
url = 'https://leria-info.univ-angers.fr/~jeanmichel.richer/ens/l1/python/tp6_numpy/iris.txt'
# sepal length, sepal width, petal lenth, petal width, species
# on charge chaque colonne, les quatre premières sont numériques
# la dernière est une chaine qui correspond à l'une des espèces
# virginica, versicolor ou setosa
long_sepal,larg_sepal,long_petal,larg_petal,especes = np.loadtxt(url, delimiter=',', dtype = "float,float,float,float,S20", unpack=True)
# créer un tableau avec les données numériques
iris = np.column_stack([long_sepal,larg_sepal,long_petal,larg_petal])
iris.astype(np.float64)
print(iris)
print(especes)
Exercice 6.6
Reprendre l'exercice précédent et afficher le minimum, maximum, la moyenne et l'écart type
pour chacune des espèces et chacune séries de données (long_sepal, larg_sepal, long_petal, larg_petal).