Académique Documents
Professionnel Documents
Culture Documents
Dans les prochains TP, nous allons utiliser des modules Python contenant des commandes bien plus
avancées que précédemment :
§ numpy contient de nombreuses commandes de calcul numérique, notamment matriciel ;
§ matplotlib contient des outils graphiques ;
§ scipy contient divers outils scientifiques.
Importez le module numpy. L’usage est de l’importer sous le nom np. Entrez donc
import numpy as np
Toutes les commandes contenues dans le module seront donc accessibles sous la forme np.commande
Les tableaux numpy ressemblent beaucoup aux listes Python. Seulement, ils sont plus performants,
et sont bien plus commodes à manipuler.
De la même façon qu’on peut utiliser des listes de listes, des listes de listes de listes, etc., il est possible
d’utiliser des tableaux numpy à plusieurs dimensions. Avec des listes ou des tableaux à une dimension,
on peut représenter des vecteurs. Et avec des listes de listes, ou des tableaux à deux dimensions, on peut
représenter des matrices. Vecteurs et matrices seront vus en temps voulu en cours de maths de MPSI !
Pour ce TP, dites-vous simplement qu’une matrice est un tableau (de nombres pour nous).
Dans ce TP, nous allons apprendre à définir, manipuler, transformer, etc., les tableaux numpy, à une
ou plusieurs dimensions.
Vous savez déjà comment accéder à une ligne ou à un élément d’une matrice représentée par une liste
de listes. . .
1 >>> M2 = [[1,2],[3,4],[5,6],[7,8]]
2 >>> M2[1] # la deuxième ligne
3 [3, 4]
4 >>> M2[0][1] # l’élément ligne 1 colonne 2
5 2
6 >>> M2[0,1] # incorrect
1
7 Traceback (most recent call last):
8 File "<stdin>", line 1, in <module>
9 TypeError: list indices must be integers, not tuple
Une deuxième syntaxe est possible avec les tableaux numpy, qui prendra toute son importance dans
la suite du TP au moment où on traitera le slicing.
1 >>> M[1] # la deuxième ligne
2 array([3, 4])
3 >>> M[0][1] # l’élément ligne 1 colonne 2
4 2
5 >>> M[0,1] # une deuxième syntaxe possible
6 2
Un tableau est un objet mutable, c’est-à-dire que l’on peut modifier un élément en affectant direc-
tement T[i,j].
2
qui est un couple d’entiers.
np.eye(4) donne la matrice diagonale identité de taille 4 (souvent noté I4 et I se prononce “aille” en
anglais. . . ).
np.diag([1,4,7,9]) donne une matrice diagonale.
Remarque : on peut aussi donner un argument entier (un seul !) à zeros et ones.
1 import numpy as np
2 print(np.zeros(100))
3 print(np.ones(50))
5 Comment aurait-on pu définir le tableau de la question précédente grâce aux listes définies en
compréhension ?
1 >>> np.array([[j+100*i for j in range(5)] for i in range(4)])
2 array([[ 0, 1, 2, 3, 4],
3 [100, 101, 102, 103, 104],
4 [200, 201, 202, 203, 204],
5 [300, 301, 302, 303, 304]])
¨ ˛
1 1 1 1
˚ 2 3 4 5
˚ ‹
‹
˚ ‹
˚ ‹
˚ ‹
˚ ‹
˚ 2 2 2 2 ‹
6 Créez le plus simplement possible la matrice : A “ ˚ ‹.
˚ 3 4 5 6
˚ ‹
‹
˚ ‹
˚ ‹
˚ ‹
˚ ‹
˝ 3 3 3 3 ‚
4 5 6 7
Voici 3 solutions, avec utilisation de listes définies en compréhension.
1 >>> np.array( [[ (i+1)/(i+j+2) for j in range(4) ] for i in range(3) ] )
2 array([[ 0.5 , 0.33333333, 0.25 , 0.2 ],
3 [ 0.66666667, 0.5 , 0.4 , 0.33333333],
4 [ 0.75 , 0.6 , 0.5 , 0.42857143]])
5 >>> np.array( [[ i/(i+j) for j in range(1,5) ] for i in range(1,4) ] )
6 array([[ 0.5 , 0.33333333, 0.25 , 0.2 ],
3
7 [ 0.66666667, 0.5 , 0.4 , 0.33333333],
8 [ 0.75 , 0.6 , 0.5 , 0.42857143]])
9 >>> np.array ( [[ (i+1)/j for j in range(i+2,i+6) ] for i in range(3) ])
10 array([[ 0.5 , 0.33333333, 0.25 , 0.2 ],
11 [ 0.66666667, 0.5 , 0.4 , 0.33333333],
12 [ 0.75 , 0.6 , 0.5 , 0.42857143]])
On aurait aussi pu procéder de façon plus classique, avec deux boucles imbriquées :
1 import numpy as np
2 M = np.zeros((3,4))
3 for i in range(3):
4 for j in range(4):
5 M[i,j] = (i+1)/(i+j+2)
6 print(M)
kπ
7 Créer simplement le tableau de tous les nombres cos pour k allant de 0 à 90.
180
1 >>> from math import pi,cos
2 >>> np.array( [ cos(k*pi/180) for k in range(91) ] )
3 array([ 1.00000000e+00, 9.99847695e-01, 9.99390827e-01,
4 9.98629535e-01, 9.97564050e-01, 9.96194698e-01,
5 9.94521895e-01, 9.92546152e-01, 9.90268069e-01,
6 9.87688341e-01, 9.84807753e-01, 9.81627183e-01,
7 9.78147601e-01, 9.74370065e-01, 9.70295726e-01,
8 9.65925826e-01, 9.61261696e-01, 9.56304756e-01,
9 9.51056516e-01, 9.45518576e-01, 9.39692621e-01,
10 9.33580426e-01, 9.27183855e-01, 9.20504853e-01,
11 9.13545458e-01, 9.06307787e-01, 8.98794046e-01,
12 8.91006524e-01, 8.82947593e-01, 8.74619707e-01,
13 8.66025404e-01, 8.57167301e-01, 8.48048096e-01,
14 8.38670568e-01, 8.29037573e-01, 8.19152044e-01,
15 8.09016994e-01, 7.98635510e-01, 7.88010754e-01,
16 7.77145961e-01, 7.66044443e-01, 7.54709580e-01,
17 7.43144825e-01, 7.31353702e-01, 7.19339800e-01,
18 7.07106781e-01, 6.94658370e-01, 6.81998360e-01,
19 6.69130606e-01, 6.56059029e-01, 6.42787610e-01,
20 6.29320391e-01, 6.15661475e-01, 6.01815023e-01,
21 5.87785252e-01, 5.73576436e-01, 5.59192903e-01,
22 5.44639035e-01, 5.29919264e-01, 5.15038075e-01,
23 5.00000000e-01, 4.84809620e-01, 4.69471563e-01,
24 4.53990500e-01, 4.38371147e-01, 4.22618262e-01,
25 4.06736643e-01, 3.90731128e-01, 3.74606593e-01,
26 3.58367950e-01, 3.42020143e-01, 3.25568154e-01,
27 3.09016994e-01, 2.92371705e-01, 2.75637356e-01,
28 2.58819045e-01, 2.41921896e-01, 2.24951054e-01,
29 2.07911691e-01, 1.90808995e-01, 1.73648178e-01,
30 1.56434465e-01, 1.39173101e-01, 1.21869343e-01,
31 1.04528463e-01, 8.71557427e-02, 6.97564737e-02,
32 5.23359562e-02, 3.48994967e-02, 1.74524064e-02,
33 6.12323400e-17])
4
Bien sûr, on aurait pu définir un tableau avec que des 0, et modifier les cases ensuite. . .
8 ‹ Vous verrez en cours de maths que la matrice de Vandermonde associée au n-uplet pa1 , ¨ ¨ ¨ , an q
est définie par A “ aj´1
` ˘
i 1ďi,jďn
. Ecrire une fonction vandermonde(A) qui renvoie le tableau numpy
représentant la matrice de Vandermonde associée à la liste de nombres A“ pa1 , ¨ ¨ ¨ , an q de longueur n.
1 import numpy as np
2 from random import randrange
3
4 def vandermonde(A):
5 n=len(A)
6 return np.array ( [ [ A[i] ** j for j in range(n) ] for i in range(n) ] )
7
8 # en parcourant A par valeurs
9 def vandermonde2(A):
10 n=len(A)
11 return np.array ( [ [ a ** j for j in range(n) ] for a in A ] )
12
13
14 if __name__=="__main__":
15 print(vandermonde([1,2,3]))
16 print(vandermonde2([1,2,3]))
17 print(vandermonde([1,2,-3,-10]))
18 print(vandermonde2([1,2,-3,-10]))
1 [[1 1 1]
2 [1 2 4]
3 [1 3 9]]
4 [[1 1 1]
5 [1 2 4]
6 [1 3 9]]
7 [[ 1 1 1 1]
8 [ 1 2 4 8]
9 [ 1 -3 9 -27]
10 [ 1 -10 100 -1000]]
11 [[ 1 1 1 1]
12 [ 1 2 4 8]
13 [ 1 -3 9 -27]
14 [ 1 -10 100 -1000]]
5
On pourrait aussi utiliser l’opérateur * de concaténation de listes.
1 >>> A = np.array( [ [0] * 8 ] * 10 )
Une petite subtilité avec les listes (voir TP sur les listes) : chaque ligne est la copie d’un unique
pointeur.
1 >>> B = [ [0] * 8 ] * 10
2 >>> B[0][0]=1000
3 >>> B
4 [[1000, 0, 0, 0, 0, 0, 0, 0], [1000, 0, 0, 0, 0, 0, 0, 0], [1000, 0, 0, 0,
0, 0, 0, 0], [1000, 0, 0, 0, 0, 0, 0, 0], [1000, 0, 0, 0, 0, 0, 0, 0],
[1000, 0, 0, 0, 0, 0, 0, 0], [1000, 0, 0, 0, 0, 0, 0, 0], [1000, 0, 0, 0,
0, 0, 0, 0], [1000, 0, 0, 0, 0, 0, 0, 0], [1000, 0, 0, 0, 0, 0, 0, 0]]
Mais cette subtilité n’existe pas avec les tableaux numpy.
1 >>> A[0,0]=1000
2 >>> A
3 array([[1000, 0, 0, 0, 0, 0, 0, 0],
4 [ 0, 0, 0, 0, 0, 0, 0, 0],
5 [ 0, 0, 0, 0, 0, 0, 0, 0],
6 [ 0, 0, 0, 0, 0, 0, 0, 0],
7 [ 0, 0, 0, 0, 0, 0, 0, 0],
8 [ 0, 0, 0, 0, 0, 0, 0, 0],
9 [ 0, 0, 0, 0, 0, 0, 0, 0],
10 [ 0, 0, 0, 0, 0, 0, 0, 0],
11 [ 0, 0, 0, 0, 0, 0, 0, 0],
12 [ 0, 0, 0, 0, 0, 0, 0, 0]])
10 La commande len existe toujours... On sait à quoi s’attendre pour la longueur d’un tableau à une
dimension. Qu’obtient-on pour la longueur d’un tableau à deux dimensions ? trois dimensions ?
1 >>> V = np.random.randint( -10, 10, 3 )
2 >>> len(V)
3 3
4 >>> M = np.random.randint( -10, 10, (3,5) )
5 >>> len(M)
6 3
7 >>> U = np.random.randint( -10, 10, (3,5,2) )
8 >>> len(U)
9 3
La longueur d’un tableau à une dimension est son nombre d’éléments ; la longueur d’une matrice est
son nombre de lignes ; la longueur d’un tableau à 3 dimensions est égale à la taille correspondant à la
dimension la plus “externe”.
6
3 >>> np.shape(V)
4 (3,)
5 >>> np.size(M)
6 15
7 >>> np.shape(M)
8 (3, 5)
9 >>> np.size(U)
10 30
11 >>> np.shape(U)
12 (3, 5, 2)
np.size renvoie le nombre de coefficients dans un tableau.
np.shape renvoie un objet de type tuple (n-uplet).
§ Sur un tableau à une dimension, np.shape donne un tuple à un élément formé du nombre de
coordonnées.
§ Avec une matrice, np.shape donne un couple formé du nombre de lignes d’abord, et du nombre
de colonnes après.
§ Avec un tableau à 3 dimension, np.shape donne un triplet.
7
D n’est PAS une matrice (il faudrait qu’il y ait le même nombre de colonnes à chaque ligne), et Python
la voit comme un tableau uni-dimensionnel. Et E est un tableau tri-dimensionnel (on pourrait mettre les
coefficients dans un parallélépipède).
3 Slicing
Grâce au slicing, on peut découper une liste, et ainsi, sélectionner un ensemble de lignes d’une matrice.
Avec les tableaux numpy, on peut faire mieux. Par exemple, comment sélectionner la deuxième colonne
(la colonne d’indice 1) d’une matrice ? Avec les listes, on pouvait faire :
1 L=[[1,2,3,4],[5,6,7,8],[9,10,11,12]]
2 print([L[i][1] for i in range(len(L))])
3 print([l[1] for l in L])
Avec les tableaux numpy, on peut bien calquer la syntaxe, mais ce n’est guère plus réjouissant.
1 T=np.array(L)
2 print([T[i][1] for i in range(len(T))])
3 print([l[1] for l in T])
Autrement, on peut faire beaucoup mieux !
8
27 [ 4, -84, -85, 71, -80, 12, 77],
28 [ 23, 35, -94, 2, 32, 10, 69],
29 [ -2, -52, 91, -49, -27, 5, -98],
30 [ 63, -2, 41, 79, 80, 60, 36],
31 [ 12, -51, -38, -70, 12, -5, 75],
32 [-96, 28, 56, -4, -79, -51, -58]])
33 >>> M[:,:]
34 array([[ 98, -42, -67, 57, -90, 85, 35, 67, -30],
35 [ 61, 70, -9, 68, 24, -65, 62, -89, -10],
36 [ -4, 98, 54, 4, 56, -58, -64, -47, -5],
37 [ 4, -84, -85, 71, -80, 12, 77, 83, -62],
38 [ 23, 35, -94, 2, 32, 10, 69, 61, -97],
39 [ -2, -52, 91, -49, -27, 5, -98, 67, -76],
40 [ 63, -2, 41, 79, 80, 60, 36, 64, 20],
41 [ 12, -51, -38, -70, 12, -5, 75, -75, -51],
42 [-96, 28, 56, -4, -79, -51, -58, -82, -91]])
Il faut avoir bien compris tout ça !
15 Comment obtenir la matrice M privée de sa dernière ligne ? et de ses deux premières colonnes ?
Simple application de ce qui précède.
9
1 import numpy as np
2 M = np.random.randint(1,10,(6,7))
3 print("M",M)
4 print("M privé de sa dernière ligne",M[:-1,:])
5 print("M privé de ses deux premières colonnes",M[:,2:])
1 >>> M = np.random.randint(-3,3,(5,5))
2 >>> M
3 array([[ 2, 1, 0, 2, -1],
4 [ 0, 0, -2, -1, -2],
5 [-3, -1, 0, 0, 1],
6 [-2, 1, 1, 2, -1],
7 [-3, 1, -2, 0, -1]])
8 >>> M[2:4,:3]=[[1000,1000,1000],[1000,1000,1000]]
9 >>> M
10 array([[ 2, 1, 0, 2, -1],
11 [ 0, 0, -2, -1, -2],
12 [1000, 1000, 1000, 0, 1],
13 [1000, 1000, 1000, 2, -1],
14 [ -3, 1, -2, 0, -1]])
15 >>> M[2:4,:3]=9999
16 >>> M
17 array([[ 2, 1, 0, 2, -1],
18 [ 0, 0, -2, -1, -2],
19 [9999, 9999, 9999, 0, 1],
20 [9999, 9999, 9999, 2, -1],
21 [ -3, 1, -2, 0, -1]])
10
17 ‹ Avec les connaissances que vous avez, créez avec légèreté et élégance les matrices :
¨ ˛
˚ 0 0 0 0 0 0 0 ‹
˚ ‹
˚ ‹
¨ ˛ ˚
˚ 0 0 0 0 0 0 0 ‹
‹
˚ 1 1 1 1 ‹ ˚ ‹
˚ ‹
˚
˚
‹
‹
˚
˚ 0 2 2 0 0 0 0 ‹
‹
˚ 1 1 1 1 ‹ ˚ ‹
˚ ‹ ˚ ‹
A“˚
˚
‹
‹ B“˚
˚ 0 2 2 0 0 0 0 ‹
‹
˚ 1 1 1 2 ‹ ˚ ‹
˚ ‹ ˚ ‹
0 0 0 0 0 0 0 ‹
˚ ‹ ˚ ‹
˝ ‚ ˚
1 6 1 1
˚ ‹
˚ ‹
0 0 0 0 0 0 0 ‹
˚ ‹
˚
˚ ‹
˝ ‚
0 0 0 0 0 0 0
11
A noter que dans le 3ème cas, on obtient une matrice de flottants, alors que dans les deux premiers
cas, on obtient des matrices d’entiers.
1 >>> M = np.random.rand(4,3)
2 >>> M
3 array([[ 0.16090807, 0.53997896, 0.790279 ],
4 [ 0.61971264, 0.98432795, 0.84869875],
5 [ 0.00599074, 0.3947013 , 0.18317299],
6 [ 0.9537028 , 0.45596474, 0.57189268]])
7 >>> M+3
8 array([[ 3.16090807, 3.53997896, 3.790279 ],
9 [ 3.61971264, 3.98432795, 3.84869875],
10 [ 3.00599074, 3.3947013 , 3.18317299],
11 [ 3.9537028 , 3.45596474, 3.57189268]])
12 >>> 4*M
13 array([[ 0.64363229, 2.15991583, 3.161116 ],
14 [ 2.47885057, 3.93731179, 3.39479498],
15 [ 0.02396295, 1.57880521, 0.73269195],
16 [ 3.81481119, 1.82385895, 2.28757072]])
17 >>> 1/M
18 array([[ 6.2147286 , 1.85192402, 1.2653759 ],
19 [ 1.61365112, 1.01592158, 1.17827439],
20 [ 166.9243302 , 2.53356143, 5.45932026],
21 [ 1.04854469, 2.19315205, 1.74857982]])
22 >>> M**2
23 array([[ 2.58914078e-02, 2.91577274e-01, 6.24540896e-01],
24 [ 3.84043758e-01, 9.68901510e-01, 7.20289561e-01],
25 [ 3.58889469e-05, 1.55789119e-01, 3.35523432e-02],
26 [ 9.09549025e-01, 2.07903843e-01, 3.27061236e-01]])
Les opérations sont appliquées à chaque terme.
19 Les tableaux se comportent-ils comme les listes du point de vue des opérations ?
Rien de ce qui est au-dessus ne fonctionne avec les listes.
20 Essayer les commandes suivantes sur deux matrices M et N de même taille de votre choix, telles que
tous les coefficients de N soient non nuls.
M+N M+N+3 M-N M*N M/N
Là encore, les opérations sont effectuées terme à terme.
12
1 >>> M = np.random.uniform(-5,5,(2,3))
2 >>> N = np.random.uniform(1,10,(2,3))
3 >>> M
4 array([[-1.74398607, -2.65079659, -2.17983514],
5 [ 0.89349767, 3.92911842, -3.70227379]])
6 >>> N
7 array([[ 8.25350413, 4.29211985, 8.51696209],
8 [ 8.95485733, 2.27261183, 7.0019683 ]])
9 >>> M+N
10 array([[ 6.50951805, 1.64132326, 6.33712696],
11 [ 9.848355 , 6.20173025, 3.2996945 ]])
12 >>> M+N+3
13 array([[ 9.50951805, 4.64132326, 9.33712696],
14 [ 12.848355 , 9.20173025, 6.2996945 ]])
15 >>> M-N
16 array([[ -9.9974902 , -6.94291644, -10.69679723],
17 [ -8.06135967, 1.6565066 , -10.70424209]])
18 >>> M*N
19 array([[-14.39399626, -11.37753665, -18.56557322],
20 [ 8.00114414, 8.92936101, -25.92320373]])
21 >>> M/N
22 array([[-0.2113025 , -0.61759612, -0.25594045],
23 [ 0.09977799, 1.72889993, -0.52874758]])
1 >>> M = np.random.randint(-50,50,(2,3))
2 >>> N = np.random.randint(1,10,(2,3))
3 >>> M
4 array([[-44, -7, -32],
5 [-16, -14, 38]])
6 >>> N
7 array([[8, 6, 5],
8 [8, 8, 3]])
9 >>> M//N
10 array([[-6, -2, -7],
11 [-2, -2, 12]])
12 >>> M%N
13 array([[4, 5, 3],
14 [0, 2, 2]])
Là encore, opérations terme à terme.
On voudrait pousser un peu plus loin en appliquant des fonctions plus compliquées, comme l’expo-
nentielle.
22 Quel module faut-il importer pour obtenir la fonction exponentielle ? Tentez d’appliquer cette
fonction à un tableau numpy.
Ça ne fonctionne pas avec la fonction exp du module math.
13
1 >>> from math import exp
2 >>> T = np.array([1,3,7,9])
3 >>> M = np.array([[1,2],[3,4],[5,6],[7,8]])
4 >>> exp(T)
5 Traceback (most recent call last):
6 File "<stdin>", line 1, in <module>
7 TypeError: only length-1 arrays can be converted to Python scalars
8 >>> exp(M)
9 Traceback (most recent call last):
10 File "<stdin>", line 1, in <module>
11 TypeError: only length-1 arrays can be converted to Python scalars
23 Avec les connaissances que vous avez, comment appliquer la fonction exponentielle à chaque terme
d’une matrice ?
Avec les listes en compréhension, tout est possible. . .
1 >>> from math import exp
2 >>> [ exp(x) for x in T ]
3 [2.718281828459045, 20.085536923187668, 1096.6331584284585,
8103.083927575384]
4 >>> [[ exp(x) for x in ligne ] for ligne in M ]
5 [[2.718281828459045, 7.38905609893065], [20.085536923187668,
54.598150033144236], [148.4131591025766, 403.4287934927351],
[1096.6331584284585, 2980.9579870417283]]
En fait, numpy dispose de sa propre fonction exponentielle.
14
Une autre solution pour “forcer” les choses à fonctionner, est de ”vectorialiser” la fonction qu’on
veut utiliser, c’est-à-dire qu’on en fait une fonction applicable à un tableau numpy. Retenez cette
possibilité.
1 >>> from math import exp
2 >>> np.vectorize(exp)(T)
3 array([ 2.71828183e+00, 2.00855369e+01, 1.09663316e+03,
4 8.10308393e+03])
5 >>> np.vectorize(exp)(M)
6 array([[ 2.71828183e+00, 7.38905610e+00],
7 [ 2.00855369e+01, 5.45981500e+01],
8 [ 1.48413159e+02, 4.03428793e+02],
9 [ 1.09663316e+03, 2.98095799e+03]])
Attention : la somme de deux matrices est bien la somme au sens mathématique que vous
verrez en cours de maths ; mais le produit de matrices (et le carré, le cube), ainsi que l’exponentielle, vus
dans ce TP, sont des opérations terme à terme, et NE correspondent PAS à la définition classique du
produit et de l’exponentielle matricielle des cours de maths. Bien sûr, on peut aussi calculer des produits
matriciels classiques avec numpy. Ceci fera l’objet d’un TP ultérieur. ` ˘
En fait, quand on fait la somme des coefficients de A*B, on définit un produit scalaire : ă A, B ą“ tr t AB
(voir un chapitre de maths de fin d’année).
De même, l’addition d’une matrice carrée avec un nombre M+3 peut être comprise en maths (avec un
abus de notation),¨ comme la somme de ˛ M avec 3 fois la matrice identité.
˚ ´3 8 1 5 ‹
˚ ‹
˚ ‹
˚ 9 6 ´2 3 ‹
˚ ‹
Par exemple ˚
˚
‹ ` 3 peut être compris en maths comme :
‹
˚ 10 1 1 ´9 ‹
˚ ‹
˚ ‹
˝ ‚
5 ´3 9 2
¨ ˛ ¨ ˛ ¨ ˛ ¨ ˛
˚ ´3 8 1 5 ‹ ˚ ´3 8 1 5 ‹ ˚ 1 0 0 0 ‹ ˚ 0 8 1
5 ‹
˚ ‹ ˚ ‹ ˚ ‹ ˚ ‹
˚ ‹ ˚ ‹ ˚ ‹ ˚ ‹
˚ 9 6 ´2 3 ‹ ˚ 9 6 ´2 3 ‹ ˚ 0 1 0 0 ‹ ˚ 9 9 ´2 3 ‹
˚ ‹ ˚ ‹ ˚ ‹ ˚ ‹
˚ ‹ ` 3I4 “ ˚ ‹ ` 3˚ ‹“˚ ‹.
˚ ‹ ˚ ‹ ˚ ‹ ˚ ‹
˚ 10 1 1 ´9 ‹ ˚ 10 1 1 ´9 ‹ 0 0 1 0 ‹ 10 1 4 ´9 ‹
‹ ˚ ‹ ˚ ˚
˚ ˚ ‹ ˚ ‹
˚ ‹ ˚ ‹ ˚ ‹ ˚ ‹
˝ ‚ ˝ ‚ ˝ ‚ ˝ ‚
5 ´3 9 2 5 ´3 9 2 0 0 0 1 5 ´3 9 5
15
10 array([2, 4, 6])
11 >>> L2*3
12 array([3, 6, 9])
5 Types ‹
Les éléments d’un tableau peuvent être a priori de n’importe quel type, mais tous les éléments d’un
même tableau doivent être du même type (c’est une différence majeure avec les listes, où on peut mettre
n’importe quoi, et la contrepartie des bonnes performances). En effet, en machine, un tableau numpy
est une zone mémoire contiguë de données.
Le type des éléments du tableau T est donné par T.dtype.
25 Essayez
1 >>> T = np.array( [ True, False, True, True ])
2 >>> T.dtype
3 xxxxxxxxxxxxxxxxxxxxxxxxx
26 Entrez par exemple T2=np.array([3,5,7,'koala',10]). Quel est le type des données de T2 ? Que
remarquez-vous si vous demandez le premier élément de T2 ?
1 >>> T2 = np.array( [ 3,5,7,’koala’,10] )
2 >>> T2.dtype
3 dtype(’<U5’)
4 >>> T2
5 array([’3’, ’5’, ’7’, ’koala’, ’10’],
6 dtype=’<U5’)
Les éléments entiers de la chaı̂nes sont convertis en chaı̂ne de caractère (3 devient '3').
16
6 Passage par référence ‹
Tout comme les listes Python, les tableaux numpy sont passés en référence aux fonctions.
30 ‹‹ Comparez
1 >>> L = [[0]]*4
2 >>> M=np.array(L)
3 >>> L
4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
5 >>> L[0][0]=100
6 >>> L
7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
8 >>> M
9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
10 >>> M[0][0]=100
11 >>> M
12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
1 >>> L = [[0]]*4
2 >>> M=np.array(L)
3 >>> L
4 [[0], [0], [0], [0]]
5 >>> L[0][0]=100
6 >>> L
7 [[100], [100], [100], [100]]
8 >>> M
9 array([[0],
10 [0],
11 [0],
12 [0]])
13 >>> M[0][0]=100
14 >>> M
15 array([[100],
16 [ 0],
17
17 [ 0],
18 [ 0]])
Comme évoqué plus haut, les lignes de L sont des copies d’un unique pointeur, c’est-à-dire qu’elles
désignent le même objet (la même liste) : donc en modifier une modifie aussi les autres.
Ce comportement ne se retrouve pas avec les tableau numpy.
On peut le voir en demandant à Python les identifiants des objets.
1 >>> id( L[0] ), id( L[1] )
2 (140269327338312, 140269327338312)
3 >>> id( M[0] ), id( M[1] )
4 (41300544, 41304464)
7 Calculs de sommes ‹
31 Définissez un tableau M (à une ou deux dimensions). Que renvoie la fonction sum avec l’argu-
ment M ?
1 >>> M = np.array([[1,2,3],[4,5,6]])
2 >>> M
3 array([[1, 2, 3],
4 [4, 5, 6]])
5 >>> sum(M)
6 array([5, 7, 9])
7 >>> sum(sum(M))
8 21
sum enlève un niveau de profondeur ; commence à faire les sommes sur les colonnes, puis on obtient
un vecteur dont il somme les composantes.
On dispose aussi de la fonction np.sum de numpy.
1 >>> M = np.array([[1,2,3],[4,5,6]])
2 >>> np.sum(M)
3 21
32 Reprenez les calculs de moyenne et d’écart-type déjà réalisés pour les listes au TP 4, et voyez
comment tout est plus facile avec numpy. Vérifiez vos résultats avec les commandes déjà existantes
np.mean et np.std.
1 >>> n=10
2 >>> A = np.random.rand(n)
3 >>> A
4 array([ 0.28022385, 0.33172203, 0.29199176, 0.0825734 , 0.56793398,
5 0.88133212, 0.21601411, 0.28712047, 0.79173467, 0.72152186])
6 >>> moyenne = sum(A)/n
7 >>> moyenne
8 0.44521682558425424
9 >>> np.mean(A)
10 0.44521682558425424
11 >>> np.sqrt ( sum( (A-moyenne)**2) / n )
12 0.2596719868357974
18
13 >>> np.std(A)
14 0.2596719868357974
33 Un vecteur étant entré comme un tableau numpy unidimensionnel, comment calculer très simple-
ment sa norme ?
1 >>> V = np.random.rand(10)
2 >>> V
3 array([ 0.72291762, 0.64474318, 0.95178733, 0.99608139, 0.4413842 ,
4 0.99856803, 0.38981072, 0.87087263, 0.20634464, 0.60676378])
5 >>> np.sqrt(sum(V**2))
6 2.3128880108772321
8 Assemblage de matrices ‹‹
34 Plusieurs commandes existent pour assembler des matrices afin d’en créer une plus grande (repeat,
tile, concatenate, hstack, vstack).
En utilisant hstack et vstack, ainsi que les commandes de création de tableaux particuliers vues plus
haut (ones, eye, diag...), créez la matrice
¨ ˛
˚ 8 5 0 0 1 0 0 0 0 4 ‹
˚ ‹
˚ ‹
˚
˚ 8 0 6 0 0 1 0 0 0 4 ‹
‹
˚ ‹
˚ ‹
˚
˚ 8 0 0 7 0 0 1 0 0 4 ‹
‹
˚ ‹
˚ ‹
˚
˚ 8 1 1 1 0 0 0 1 0 4 ‹
‹
˚ ‹
˚ ‹
8 1 1 1 0 0 0 0 1 4 ‹
˚ ‹
˚
˚ ‹
˝ ‚
8 3 3 3 3 3 3 3 3 3
19
8 5 0 0 1 0 0 0 0 4
8 0 6 0 0 1 0 0 0 4
8 0 0 7 0 0 1 0 0 4
8 1 1 1 0 0 0 1 0 4
8 1 1 1 0 0 0 0 1 4
8 3 3 3 3 3 3 3 3 3
1 >>> A = 8*np.ones((6,1))
2 >>> B = np.diag([5,6,7])
3 >>> C = np.eye(5)
4 >>> D = np.ones((2,3))
5 >>> E = 4*np.ones((5,1))
6 >>> F = 3*np.ones((1,9))
7 >>>
8 >>> G = np.vstack((B,D))
9 >>> H = np.hstack((G,C,E))
10 >>> I = np.vstack((H,F))
11 >>> J = np.hstack((A,I))
12 >>> J
13 array([[ 8., 5., 0., 0., 1., 0., 0., 0., 0., 4.],
14 [ 8., 0., 6., 0., 0., 1., 0., 0., 0., 4.],
15 [ 8., 0., 0., 7., 0., 0., 1., 0., 0., 4.],
16 [ 8., 1., 1., 1., 0., 0., 0., 1., 0., 4.],
17 [ 8., 1., 1., 1., 0., 0., 0., 0., 1., 4.],
18 [ 8., 3., 3., 3., 3., 3., 3., 3., 3., 3.]])
Remarque. Comme évoqué plus haut, hstack et vstack ne modifient pas les tableaux qui leur sont
passés en argument, mais renvoient un nouveau tableau.
20
9 Pour les curieux : traitement d’images ‹‹
En machine, les images couleurs sont des tableaux de triplets de nombres entre 0 et 255 représentant
les taux respectifs de rouge, vert et bleu.
Une image de h pixels de hauteurs par ` pixels de largeur, est représentée par une matrice à h lignes
et ` colonnes.
On suppose qu’il existe un fichier image.jpg dans le répertoire courant. Ou peut-être, si vous travaillez
en salle de TP, feriez-vous mieux de travailler avec un fichier au format png. . .
35 Si vraiment vous avez terminé le reste, vous pouvez tenter de comprendre le petit programme
images.py, placé sur mon site web pour vous, et que vous exécuterez la première fois en tant que script
(Ctrl+Shift+E).
1 import imageio
2 import matplotlib.pyplot as plt
3 import numpy as np
4
5 image = imageio.imread("image.jpg")
6 taille=np.shape(image)
7 largeur=taille[1] ; hauteur=taille[0]
8 print("largeur: ",largeur," hauteur: ",hauteur)
9
10 # 1 pixel sur 3
11 image2 = np.array([[image[i][j] for j in range(largeur) if j%3==0] for i in range(
hauteur) if i%3==0])
12
13 # un petit morceau de l’image
14 image3 = np.array([[image[i][j] for j in range(400,700) ] for i in range(100,200)
])
15
16 plt.imshow(image2)
17 plt.show()
18 plt.imshow(image3)
19 plt.show()
Le traitement d’images fera l’objet d’un TP entier en MP.
21