Numpy et calcul matriciel

Numpy et calcul matriciel

Création de Matrices

Le type de base de la bibliothèque Numpy est le ndarray (N-dimensionnal array) : Tableau à N dimensions (1D, 2D, 3D, … )

  • ndarray 1D : en python, le type de base liste correspond à un nd-array 1D mais les calculs avec le type ndarray sont plus rapides.
  • ndarray 2D peut être représenté comme un tableau dans un tableur
  • ndarray 3D ( ex : image couleur RGB )

L’attribut shape ( dimensions ) :

  • ndim = 1 => shape = (2,) => 2 lignes
  • ndim = 2 => shape = (2,3) => 2 lignes 2 colonnes
  • ndim = 3 => shape = (2,3,3) => 2 lignes 2 colonnes 3 profondeurs
    REMARQUE : shape est un tuple ( liste constante ), shape[0]=2 : chaque élément de shape est une constante
import numpy as np 

tableau = np.array([1,2,3]) # creation de l'objet tableau, appartenant à la classe numpy  

numpy_2.svg

print(tableau.size)
3
# Dimensions du tableau : shape est un ATTRIBUT de l'OBJET tableau appartenant à la CLASSE numpy
tableau.shape
(3,)
# Nombre d'éléments dans le tableau
tableau.size
3
tab_2d_23 = np.array( [[1,2,3], [4,5,6]] ) # 2 lignes ( 0 1 ) 3 colonnes ( 0 1 2 )
print(tab_2d_23.shape)
tab_2d_23
(2, 3)
array([[1, 2, 3],
       [4, 5, 6]])

numpy_1.svg

tab_2d_32 = np.array( [[1,2], [3,4] , [5,6]] ) # 3 lignes ( 0 1 2 )   2 colonnes ( 0 1 )
print(tab_2d_32.shape)
tab_2d_32
(3, 2)
array([[1, 2],
       [3, 4],
       [5, 6]])

numpy_3.svg

# accès aux éléments du tableau

print(tab_2d_32[0,1]) # attention le premier élément est à l'index 0
2

numpy_4.svg

# Matrice de 1
A = np.ones((4,2))
print('A =\n',A)
A =
 [[1. 1.]
 [1. 1.]
 [1. 1.]
 [1. 1.]]

numpy_5.svg


Concatenation / Redisposition

A =  np.zeros((4,2))
B =  np.ones((4,2))
print('A =\n',A)
print('B =\n',B)
A =
 [[0. 0.]
 [0. 0.]
 [0. 0.]
 [0. 0.]]
B =
 [[1. 1.]
 [1. 1.]
 [1. 1.]
 [1. 1.]]
# horizontal stack : on colle côte à côte
C = np.hstack((A,B)) 
# équivalent à : 
C = np.concatenate((A,B), axis=1) # axis 0 : axe vertical, axis 1 : axe horizontal
print(C.shape)
C
(4, 4)
array([[0., 0., 1., 1.],
       [0., 0., 1., 1.],
       [0., 0., 1., 1.],
       [0., 0., 1., 1.]])

numpy_6.svg

D = np.vstack((A,B))
# équivalent à : 
D = np.concatenate((A,B), axis=0)
print(D.shape)
D
(8, 2)
array([[0., 0.],
       [0., 0.],
       [0., 0.],
       [0., 0.],
       [1., 1.],
       [1., 1.],
       [1., 1.],
       [1., 1.]])

numpy_7.svg

D = D.reshape((4,4)) # redisposition, il faut le même nombre d'éléments
D
array([[0., 0., 0., 0.],
       [0., 0., 0., 0.],
       [1., 1., 1., 1.],
       [1., 1., 1., 1.]])
A=np.array([1,2,3])
A.shape
(3,)
A = A.reshape((A.shape[0],1)) # --> forçage à un shape (x,1) pour nd=1, nécessaire pour certains calculs  
A.shape
(3, 1)
A = A.squeeze() # --> forçage à un shape (x,)
A.shape
(3,)
D = D.ravel() # --> On écrase tout sur une seule ligne
D
array([0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1., 1., 1., 1., 1.])

Indexing / Slicing / Masking

# 2D array  ; axe 0 : lignes ; axe 1 : colonnes 

A = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(A)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
print(A[0,0])
print(A[1,2])
1
6

numpy_8.svg

# Slicing
col = A[:,0]  # Colonne 0 : on prend tout
col
array([1, 4, 7])

numpy_9.svg

lin = A[0,:] # ligne 0 : on prend tout
lin
array([1, 2, 3])

numpy_10.svg

B = A[0:2,0:2] # lignes 0 à 2 ( 2 exclue ), colonnes 0 à 2 ( 2 exclue )
B
array([[1, 2],
       [4, 5]])

numpy_11.svg

A[0:2,0:2] = 10
A
array([[10, 10,  3],
       [10, 10,  6],
       [ 7,  8,  9]])

numpy_12.svg

A[:,-2:] # affichage 2 dernières colonnes
array([[10,  3],
       [10,  6],
       [ 8,  9]])

numpy_13.svg

C = np.zeros((5,5))
C[::2,::2] = 1 # toutes les valeurs avec un pas de 2
C
array([[1., 0., 1., 0., 1.],
       [0., 0., 0., 0., 0.],
       [1., 0., 1., 0., 1.],
       [0., 0., 0., 0., 0.],
       [1., 0., 1., 0., 1.]])
# Masquage ( Boolean Indexing )
A = np.random.randint(0,10,[5,5])
print(A)
print(A.shape)
print(A < 5)
[[3 4 6 5 6]
 [5 9 5 4 1]
 [6 7 4 5 6]
 [8 6 7 9 5]
 [4 8 6 9 9]]
(5, 5)
[[ True  True False False False]
 [False False False  True  True]
 [False False  True False False]
 [False False False False False]
 [ True False False False False]]
A[A<5]=123 # tous les nombres inférieurs à 5 deviennent 10
A
array([[123, 123,   6,   5,   6],
       [  5,   9,   5, 123, 123],
       [  6,   7, 123,   5,   6],
       [  8,   6,   7,   9,   5],
       [123,   8,   6,   9,   9]])
# filtrage : 
A_filtered = A[A<9]
print(A_filtered)
print(A_filtered.shape)
[6 5 6 5 5 6 7 5 6 8 6 7 5 8 6]
(15,)

Opération sur les éléments des tableaux



A = np.random.seed(0)
A = np.random.randint(-10,10,[2,3])
print(A)
[[  2   5 -10]
 [ -7  -7  -3]]

numpy_14.svg

# somme de tous les éléments du tableau
s = A.sum()
s
-20

numpy_15.svg

# somme des colonnes 
s= A.sum(axis=0) # axe 0 = VERTICAL ; axe 1 = axe HORIZONTAL
s
array([ -5,  -2, -13])

numpy_16.svg

# somme cumulée
s = A.cumsum() 
s
array([  2,   7,  -3, -10, -17, -20])
# position du minimum 
A.argmin( axis=0 ) # POSITION du minimum pour chaque colonne  
array([1, 1, 0])
A.argsort( axis=1 ) # retourne les index dans l'ordre de tri  
# du tableau, sans modifier le tableau
array([[2, 0, 1],
       [0, 1, 2]])

numpy_18.svg

A.sort( axis=1 ) # tri --> A est modifié
A
array([[-10,   2,   5],
       [ -7,  -7,  -3]])

numpy_17.svg

np.exp(A) # exponentielle pour chaque nombre
array([[4.53999298e-05, 7.38905610e+00, 1.48413159e+02],
       [9.11881966e-04, 9.11881966e-04, 4.97870684e-02]])

Statistiques

A.min()
-10
A.max()
5
# Moyenne
A.mean()
-3.3333333333333335
A.mean(axis = 0) # Moyenne sur chaque colonne  
array([-8.5, -2.5,  1. ])
A.std() # ecart type
5.312459150169743
A.var() # variance
28.222222222222225
np.corrcoef(A) # corrélation entre différentes lignes et colonnes
array([[1.        , 0.65465367],
       [0.65465367, 1.        ]])
values, counts = np.unique(A,return_counts=True) # nombre d'occurences dans un tableau
print( values, counts )
[-10  -7  -3   2   5] [1 2 1 1 1]
# NaN corrections  
A = np.random.randn(5,5)
A[0,3]=np.nan
A[4,4]=np.nan
A
array([[ 1.86755799, -0.97727788,  0.95008842,         nan, -0.10321885],
       [ 0.4105985 ,  0.14404357,  1.45427351,  0.76103773,  0.12167502],
       [ 0.44386323,  0.33367433,  1.49407907, -0.20515826,  0.3130677 ],
       [-0.85409574, -2.55298982,  0.6536186 ,  0.8644362 , -0.74216502],
       [ 2.26975462, -1.45436567,  0.04575852, -0.18718385,         nan]])
# Calcul de la moyenne sans considérer les nan
np.nanmean(A)
0.21961182192574394
# compter le nombre de nan :
np.isnan(A) # masque booleen  
np.isnan(A).sum()/A.size # taux de nan dans le tableau
0.08
A[np.isnan(A)] = 0 # 0 remplace nan
A
array([[ 1.86755799, -0.97727788,  0.95008842,  0.        , -0.10321885],
       [ 0.4105985 ,  0.14404357,  1.45427351,  0.76103773,  0.12167502],
       [ 0.44386323,  0.33367433,  1.49407907, -0.20515826,  0.3130677 ],
       [-0.85409574, -2.55298982,  0.6536186 ,  0.8644362 , -0.74216502],
       [ 2.26975462, -1.45436567,  0.04575852, -0.18718385,  0.        ]])

Calcul Matriciel

# Algèbre linéaire linalg
A = np.ones((2,3))
B = np.ones((3,2))
print('A=\n', A)
print('B=\n', B)
A=
 [[1. 1. 1.]
 [1. 1. 1.]]
B=
 [[1. 1.]
 [1. 1.]
 [1. 1.]]
A.T # Transpose matrice
array([[1., 1.],
       [1., 1.],
       [1., 1.]])

numpy_19.svg

res = A.dot(B) # Produit matriciel (2,3)*(3,2)=(2,2)
res
array([[3., 3.],
       [3., 3.]])

numpy_20.svg