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 :

  1. import numpy as np
  2.  
  3. # definition
  4. tableau = np.array( [10, 11, 12, 13] )
  5.  
  6. # affiche le tableau
  7. print("tableau = ", tableau)
  8.  
  9. # affiche le premier et le second élément
  10. print("tableau[0] = ", tableau[0])
  11. print("tableau[1] = ", tableau[1])
  12.  
  13. print("nombre d'éléments = ", tableau.size)
  14.  
  15. print("nombre de dimensions = ",  tableau.ndim)
  16.  
  17. print("dimension(s) = ", tableau.shape)
  18. 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 :

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 :

  1. import numpy as np
  2.  
  3. # tableau composé de 5 fois la valeur 0.0 (réel/flottant)
  4. tableau_reels = np.zeros(5)
  5. print(tableau_reels)
  6.  
  7. # tableau composé de 5 fois la valeur 0 (entier)
  8. # on précise ici le type de représentation qui sera 'int'
  9. tableau_entiers = np.zeros(5, dtype=int)
  10. print(tableau_entiers)
  11.  
  12. # tableau de 15 entiers initialisés à 1 (entier)
  13. tableau_entiers = np.ones(15, dtype=int)
  14. 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 :

  1. import numpy as np
  2.  
  3. tableau_reels = np.ones(10)
  4. tableau_reels *= 7
  5. print(tableau_reels)
  6.  
  7. tableau_reels = np.full(10, 7.0)
  8. 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 :

  1. import numpy as np
  2.  
  3. tableau_entiers = np.arange(1,10)
  4. print(tableau_entiers)
  5.  
  6. tableau_entiers = np.arange(1,30,3)
  7. print(tableau_entiers)
  8.  
  9. tableau_entiers = np.arange(start = 1, stop = 30, step = 3)
  10. 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 :

  1. import numpy as np
  2.  
  3. # créer un tableau de 10 valeurs comprises dans [0, 1.0[
  4. tableau_alatoire_reels = np.random.random( 10 )
  5. print(tableau_alatoire_reels)
  6.  
  7. # créer un tableau de 10 valeurs entières comprises
  8. # entre -7 et 7
  9. tableau_alatoire_entiers = np.random.randint(-7, 8, 10)
  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.

  1. import numpy as np
  2.  
  3. tableau_entiers = np.array([1,2,3])
  4. print(tableau_entiers)
  5.  
  6. # modification non prise en compte
  7. np.append(tableau_entiers, 4)
  8. print(tableau_entiers)
  9.  
  10. # prise en compte de la valeur en réassignant le tableau
  11. tableau_entiers = np.append(tableau_entiers, 4)
  12. 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.

  1. import numpy as np
  2.  
  3. tableau_entiers = np.array([1,2,3,4,5,6])
  4. print(tableau_entiers)
  5.  
  6. tableau_entiers = np.insert(tableau_entiers, 3, -7)
  7. print(tableau_entiers)
  8.  
  9. tableau_entiers = np.insert(tableau_entiers, 0, -3)
  10. 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.

  1. import numpy as np
  2.  
  3. tableau_entiers = np.array([1,2,3,4,5,6])
  4. print(tableau_entiers)
  5.  
  6. tableau_entiers = np.delete(tableau_entiers, 3)
  7. 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 :

  1. import numpy as np
  2.  
  3. tableau_entiers = np.array([10,11,12,13,14,15,16,17,18])
  4.  
  5. print(tableau_entiers[2:5])
  6.  
  7. print(tableau_entiers[:3])
  8.  
  9. 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é :

  1. import numpy as np
  2.  
  3. tableau_entiers = np.array([1,2,3,4,5,6,5,6,5,3])
  4. indices = np.where(tableau_entiers == 5)
  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 :

  1. import numpy as np
  2.  
  3. # première méthode
  4. # condition entre crochets du tableau
  5. tableau_entiers = np.arange(1,30,2)
  6. print(tableau_entiers)
  7. nouveau_tableau = tableau_entiers[(tableau_entiers > 10) & (tableau_entiers <= 15)]
  8. print(nouveau_tableau)
  9.  
  10. # deuxième méthode
  11. # choix des indices correspondant aux critères
  12. selection = (tableau_entiers > 10) & (tableau_entiers <= 15)
  13. nouveau_tableau = tableau_entiers[ selection ]
  14. 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

  1. import numpy as np
  2.  
  3. # fonction à appliquer
  4. def carre(x):
  5.     return x*x
  6.  
  7. # fonction vectorisée (qui peut s'appliquer en parallèle sur
  8. # chacun des éléments d'un tableau)
  9. vec_carre = np.vectorize(carre)
  10.  
  11. tableau_entiers = np.array([10,11,12,13,14,15,16,17,18])
  12.  
  13. tableau_entiers = vec_carre(tableau_entiers)
  14.  
  15. 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 :

  1. import numpy as np
  2.  
  3. # définition avec lignes
  4. matrice_entiers = np.array([[11,12,13,14],[21,22,23,24]])
  5.  
  6. # ou liste de valeurs et reshape
  7. matrice_entiers = np.array([11,12,13,14,21,22,23,24]).reshape(2,4)
  8.  
  9. print(matrice_entiers)
  10. print(matrice_entiers.shape)
  11. print("dimension sur y=", matrice_entiers.shape[0])
  12. print("dimension sur x=", matrice_entiers.shape[1])
  13. print("nombre d'éléments=", matrice_entiers.size)
  14. print("première ligne=", matrice_entiers[0])
  15. print("deuxième ligne=", matrice_entiers[1])
  16. 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 :

  1. import numpy as np
  2.  
  3. matrice_entiers = np.ones((5,3))
  4.  
  5. print(matrice_entiers)
  6. print(matrice_entiers.shape)
  7. print("dimension sur y=", matrice_entiers.shape[0])
  8. print("dimension sur x=", matrice_entiers.shape[1])
  9. print("nombre d'éléments=", matrice_entiers.size)
  10. print("première ligne=", matrice_entiers[0])
  11. print("deuxième ligne=", matrice_entiers[1])
  12. print(matrice_entiers[0][2])
  13.  
  14.  
  15. id_ligne = 0
  16. for ligne in matrice_entiers:
  17.     print("ligne ", id_ligne, " : ", ligne)
  18.     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é :

  1. import numpy as np
  2.  
  3. matrice_entiers = np.eye(5)
  4.  
  5. print(matrice_entiers)
  6. print(matrice_entiers.shape)
  7. print("dimension sur y=", matrice_entiers.shape[0])
  8. print("dimension sur x=", matrice_entiers.shape[1])
  9. print("nombre d'éléments=", matrice_entiers.size)
  10. print("première ligne=", matrice_entiers[0])
  11. print("deuxième ligne=", matrice_entiers[1])
  12. print(matrice_entiers[0][2])
  13. matrice_entiers[0][2] = -777
  14.  
  15. id_ligne = 0
  16. for ligne in matrice_entiers:
  17.     print("ligne ", id_ligne, " : ", ligne)
  18.     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

  1. import numpy as np
  2.  
  3. matrice_entiers = np.ones((5,3))
  4. colonne = np.array([8,9,10,11,12]).reshape(5,1)
  5. matrice_entiers = np.append(matrice_entiers, colonne, axis=1 )
  6.  
  7. 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

  1.  
  2. import numpy as np
  3.  
  4. matrice_entiers = np.ones((5,3))
  5. colonne = np.arange(1,4)
  6. matrice_entiers = np.insert(matrice_entiers, 1, colonne, axis=0 )
  7.  
  8. 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

  1. import numpy as np
  2.  
  3. matrice_entiers = np.ones((5,3))
  4. colonne = np.arange(1,6)
  5. matrice_entiers = np.insert(matrice_entiers, 1, colonne, axis=1 )
  6.  
  7. 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

  1. import numpy as np
  2.  
  3. matrice_entiers = np.arange(1,16).reshape(5,3)
  4. print(matrice_entiers)
  5.  
  6. matrice_entiers = np.delete(matrice_entiers, 1, axis=0)
  7. 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

  1. import numpy as np
  2.  
  3. matrice_entiers = np.arange(1,16).reshape(5,3)
  4. print(matrice_entiers)
  5.  
  6. matrice_entiers = np.delete(matrice_entiers, 1, axis=1)
  7. 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].

  1. 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) :

  1. import numpy as np
  2.  
  3. url = 'https://leria-info.univ-angers.fr/~jeanmichel.richer/ens/l1/python/tp6_numpy/iris.txt'
  4.  
  5.  
  6. # sepal length, sepal width, petal lenth, petal width, species
  7. # on charge chaque colonne, les quatre premières sont numériques
  8. # la dernière est une chaine qui correspond à l'une des espèces
  9. # virginica, versicolor ou setosa
  10. long_sepal,larg_sepal,long_petal,larg_petal,especes = np.loadtxt(url, delimiter=',', dtype = "float,float,float,float,S20", unpack=True)
  11.  
  12. # créer un tableau avec les données numériques
  13. iris = np.column_stack([long_sepal,larg_sepal,long_petal,larg_petal])
  14. iris.astype(np.float64)
  15. print(iris)
  16. 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).