You are on page 1of 14

Plusieurs possibilités:

a partir de listes ou n-uplets Python


Numpy (tableaux de données multi-dimensionnels) en utilisant des fonctions dédiées, telles que arange, linspace, etc.
par chargement à partir de fichiers
et matplotlib (visualisation en 2D et 3D pour Python)
A partir de listes
Slim Essid : slim.essid@telecom-paristech.fr
Alexandre Gramfort : alexandre.gramfort@telecom-paristech.fr Au moyen de la fonction numpy.array :

adapté du travail de J.R. Johansson (robert@riken.jp) http://dml.riken.jp/~rob/ In [6]: # un vecteur: l'argument de la fonction est une liste Python
v = array([1,2,3,4])
In [3]: # et JUSTE POUR MOI (pour avoir les figures dans le notebook) print v
%pylab inline
[1 2 3 4]
Welcome to pylab, a matplotlib-based Python environment [backend:
module://IPython.zmq.pylab.backend_inline]. On peut alors visualiser ces données :
For more information, type 'help(pylab)'.
In [7]: figure()
plot(v,'r')
Introduction xlabel('x')
ylabel('v')
title('Exemple simple')
show()
numpy est un module utilisé dans presque tous les projets de calcul numérique sous Python
Il fournit des structures de données performantes pour la manipulation de vecteurs, matrices et
tenseurs plus généraux
numpy est écrit en C et en Fortran d'où ses performances élevées lorsque les calculs sont vectorisés
(formulés comme des opérations sur des vecteurs/matrices)

matplotlib est un module performant pour la génération de graphiques en 2D et 3D


syntaxe très proche de celle de Matlab
supporte texte et étiquettes en
sortie de qualité dans divers formats (PNG, PDF, SV, EPS...)
interface graphique intéractive pour explorer les figures
guiqwt.pyplot est une alternative intéressante qui reprend la syntaxe de matplotlib (plus
récente, encore peu utilisée)

Pour utiliser numpy et matplotlib il faut commencer par les importer :

In [4]: import numpy as np


import matplotlib.pyplot as plt
On peut omettre show(), lorsque la méthode ion() a été appelée ; c'est le cas dans Spyder et pylab
On peut plus simplement faire :
Pour définir une matrice :

In [5]: from numpy import *


In [8]: # une matrice: l'argument est une liste emboitée
from pylab import *
M = array([[1, 2], [3, 4]])
print M
pylab étant un environnement Python pour le calcul scientifique intégrant les modules numpy et
matplotlib.pyplot (sauf quelques fonctions). [[1 2]
[3 4]]

Arrays numpy Les objets v et M sont tous deux du type ndarray (fourni par numpy)

Dans la terminologie numpy, vecteurs, matrices et autres tenseurs sont appelés arrays. In [9]: type(v), type(M)

Out[9]: (numpy.ndarray, numpy.ndarray)


Création d'arrays numpy
v et M ne diffèrent que par leur taille, que l'on peut obtenir via la propriété shape :
[ 3.+0.j, 4.+0.j]])
In [10]: v.shape

Out[10]: (4,) Autres types possibles avec dtype : int, float, complex, bool, object, etc.
On peut aussi spécifier la précision en bits: int64, int16, float128, complex128.
In [11]: M.shape

Out[11]: (2, 2) Utilisation de fonction de génération d'arrays


Pour obtenir le nombre d'éléments d'un array :
arange

In [12]: M.size In [18]: # create a range


Out[12]: 4 x = arange(0, 10, 1) # arguments: start, stop, step

On peut aussi utiliser numpy.shape et numpy.size x

In [13]: shape(M) Out[18]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Out[13]: (2, 2)
In [19]: x = arange(-1, 1, 0.1)
Les arrays ont un type qu'on obtient via dtype:
x

In [14]: M.dtype Out[19]: array([ -1.00000000e+00, -9.00000000e-01, -8.00000000e-01,


-7.00000000e-01, -6.00000000e-01, -5.00000000e-01,
Out[14]: dtype('int32') -4.00000000e-01, -3.00000000e-01, -2.00000000e-01,
-1.00000000e-01, -2.22044605e-16, 1.00000000e-01,
Les types doivent être respectés lors d'assignations à des arrays 2.00000000e-01, 3.00000000e-01, 4.00000000e-01,
5.00000000e-01, 6.00000000e-01, 7.00000000e-01,
In [15]: M[0,0] = "hello" 8.00000000e-01, 9.00000000e-01])

----------------------------------------------------------------------- linspace and logspace


----
ValueError Traceback (most recent call In [20]: # avec linspace, le début et la fin SONT inclus
last) linspace(0, 10, 25)
<ipython-input-15-a09d72434238> in <module>()
----> 1 M[0,0] = "hello" Out[20]: array([ 0. , 0.41666667, 0.83333333, 1.25 ,
1.66666667, 2.08333333, 2.5 , 2.91666667,
ValueError: invalid literal for long() with base 10: 'hello' 3.33333333, 3.75 , 4.16666667, 4.58333333,
5. , 5.41666667, 5.83333333, 6.25 ,
6.66666667, 7.08333333, 7.5 , 7.91666667,
Attention ! 8.33333333, 8.75 , 9.16666667, 9.58333333, 10.
])

In [16]: a = array([1,2,3])
a[0] = 3.2 In [21]: print e
print a print logspace(0, 10, 10, base=e)
a.dtype 2.71828182846
[3 2 3] [ 1.00000000e+00 3.03773178e+00 9.22781435e+00 2.80316249e+01
8.51525577e+01 2.58670631e+02 7.85771994e+02 2.38696456e+03
Out[16]: dtype('int32') 7.25095809e+03 2.20264658e+04]

On peut définir le type de manière explicite en utilisant le mot clé dtype en argument: mgrid

In [17]: M = array([[1, 2], [3, 4]], dtype=complex) In [22]: x, y = mgrid[0:5, 0:5]


M

Out[17]: array([[ 1.+0.j, 2.+0.j], In [23]: x

Out[23]: array([[0, 0, 0, 0, 0],


Out[23]: array([[0, 0, 0, 0, 0],
[1, 1, 1, 1, 1],
[2, 2, 2, 2, 2],
[3, 3, 3, 3, 3],
[4, 4, 4, 4, 4]])

In [24]: y

Out[24]: array([[0, 1, 2, 3, 4],


[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]])

Données aléatoires
diag
In [25]: from numpy import random
In [29]: # une matrice diagonale
In [26]: # tirage uniforme dans [0,1] diag([1,2,3])
random.rand(5,5)
Out[29]: array([[1, 0, 0],
Out[26]: array([[ 0.9233761 , 0.42880142, 0.58351343, 0.12834447, [0, 2, 0],
0.17716305], [0, 0, 3]])
[ 0.31042569, 0.56215271, 0.0380865 , 0.8392456 ,
0.06301622], In [30]: # diagonale avec décalage par rapport à la diagonale principale
[ 0.04295119, 0.29258217, 0.71466429, 0.41924466, diag([1,2,3], k=1)
0.73821216],
[ 0.36466787, 0.18688405, 0.17281408, 0.96626847, Out[30]: array([[0, 1, 0, 0],
0.54234518], [0, 0, 2, 0],
[ 0.6851275 , 0.64834141, 0.33608157, 0.09813496, [0, 0, 0, 3],
0.06831042]]) [0, 0, 0, 0]])

In [27]: # tirage suivant une loi normale standard zeros et ones


random.randn(5,5)
In [31]: zeros((3,3)) # attention zeros(3,3) est FAUX
Out[27]: array([[ 6.37138976e-01, -5.97454842e-01, -5.34241653e-01,
9.81881154e-01, -1.37475441e+00], Out[31]: array([[ 0., 0., 0.],
[ -2.23932693e+00, -4.25192062e-01, 6.17178169e-01, [ 0., 0., 0.],
1.95858661e-01, -3.10843336e-04], [ 0., 0., 0.]])
[ -1.23164733e+00, -4.21897154e-01, 2.36600964e-01,
-1.94529723e+00, 5.92087436e-01],
In [32]: ones((3,3))
[ 1.12800665e-01, 1.38876333e+00, 2.04482098e+00,
-2.36572040e+00, 5.15929286e-01],
[ -2.42830197e-02, -9.25939420e-03, -1.29759966e-01, Out[32]: array([[ 1., 1., 1.],
4.55718805e-01, -1.11077051e+00]]) [ 1., 1., 1.],
[ 1., 1., 1.]])
Affichage de l'histogramme des tirages

In [28]: a = random.randn(1000) Fichiers d'E/S


hist(a)

Out[28]: (array([ 8, 34, 87, 152, 200, 218, 160, 88, 35, 18]),
Fichiers séparés par des virgules (CSV)
array([-2.87253254, -2.31280465, -1.75307676, -1.19334887,
-0.63362098, Un format fichier classique est le format CSV (comma-separated values), ou bien TSV (tab-separated values).
-0.07389309, 0.4858348 , 1.04556269, 1.60529058, 2.16501847, Pour lire de tels fichiers utilisez numpy.genfromtxt. Par exemple:
2.72474636]),
<a list of 10 Patch objects>)
In [33]: data = genfromtxt('data.csv', delimiter=',')
data
Out[33]: array([[ 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10.], Autres propriétés des arrays numpy
[ 1., 3., 3., 4., 6.],
[ 1., 2., 3., 4., 20.]])
In [41]: M.itemsize # octets par élément
In [34]: data.shape
Out[41]: 8
Out[34]: (4, 5)

In [42]: M.nbytes # nombre d'octets


A l'aide de numpy.savetxt on peut enregistrer un array numpy dans un fichier txt:
Out[42]: 72
In [35]: M = rand(3,3)

M In [43]: M.ndim # nombre de dimensions

Out[35]: array([[ 0.32065774, 0.35600274, 0.93337945], Out[43]: 2


[ 0.15606578, 0.52379937, 0.28571533],
[ 0.33599669, 0.46124275, 0.09431427]])
Manipulation d'arrays
In [36]: savetxt("random-matrix.txt", M)

In [37]: !cat random-matrix.txt Indexation


#!type random-matrix.txt

3.206577386307648547e-01 3.560027430397629811e-01 In [44]: # v est un vecteur, il n'a qu'une seule dimension -> un seul indice
9.333794526422668492e-01 v[0]
1.560657844009143425e-01 5.237993704258564476e-01
2.857153341794410606e-01 Out[44]: 1
3.359966948652352015e-01 4.612427499341457127e-01
9.431427012755255745e-02
In [45]: # M est une matrice, ou un array à 2 dimensions -> deux indices
M[1,1]
In [38]: savetxt("random-matrix.csv", M, fmt='%.5f', delimiter=',') # fmt
spécifie le format
Out[45]: 0.52379937042585645
!cat random-matrix.csv
#!type random-matrix.csv Contenu complet :

0.32066,0.35600,0.93338 In [46]: M
0.15607,0.52380,0.28572
0.33600,0.46124,0.09431 Out[46]: array([[ 0.32065774, 0.35600274, 0.93337945],
[ 0.15606578, 0.52379937, 0.28571533],
[ 0.33599669, 0.46124275, 0.09431427]])
Format de fichier Numpy natif
Pour sauvegarder et recharger des array numpy : numpy.save et numpy.load : La deuxième ligne :

In [39]: np.save("random-matrix.npy", M) In [47]: M[1]

#!file random-matrix.npy Out[47]: array([ 0.15606578, 0.52379937, 0.28571533])

On peut aussi utiliser :


In [40]: np.load("random-matrix.npy")
In [48]: M[1,:] # 2 ème ligne (indice 1)
Out[40]: array([[ 0.32065774, 0.35600274, 0.93337945],
[ 0.15606578, 0.52379937, 0.28571533], Out[48]: array([ 0.15606578, 0.52379937, 0.28571533])
[ 0.33599669, 0.46124275, 0.09431427]])

In [49]: M[:,1] # 2 ème colonne (indice 1)

Out[49]: array([ 0.35600274, 0.52379937, 0.46124275])


Out[49]: array([ 0.35600274, 0.52379937, 0.46124275]) Out[59]: array([ 1, -2, -3])

On peut assigner des nouvelles valeurs à certaines cellules :


In [60]: A[3:] # à partir de l'indice 3
In [50]: M[0,0] = 1
Out[60]: array([4, 5])

In [51]: M On peut utiliser des indices négatifs :

Out[51]: array([[ 1. , 0.35600274, 0.93337945], In [61]: A = array([1,2,3,4,5])


[ 0.15606578, 0.52379937, 0.28571533],
[ 0.33599669, 0.46124275, 0.09431427]])
In [62]: A[-1] # le dernier élément

In [52]: # on peut aussi assigner des lignes ou des colonnes Out[62]: 5


M[1,:] = 0
M[:,2] = -1
In [63]: A[-3:] # les 3 derniers éléments

In [53]: M Out[63]: array([3, 4, 5])

Out[53]: array([[ 1. , 0.35600274, -1. ], Le slicing fonctionne de façon similaire pour les array multi-dimensionnels
[ 0. , 0. , -1. ],
[ 0.33599669, 0.46124275, -1. ]])
In [64]: A = array([[n+m*10 for n in range(5)] for m in range(5)])

A
Slicing ou accès par tranches
Out[64]: array([[ 0, 1, 2, 3, 4],
Slicing fait référence à la syntaxe M[start:stop:step] pour extraire une partie d'un array : [10, 11, 12, 13, 14],
[20, 21, 22, 23, 24],
In [54]: A = array([1,2,3,4,5]) [30, 31, 32, 33, 34],
A [40, 41, 42, 43, 44]])

Out[54]: array([1, 2, 3, 4, 5]) In [65]: # a block from the original array


A[1:4, 1:4]
In [55]: A[1:3]
Out[65]: array([[11, 12, 13],
Out[55]: array([2, 3]) [21, 22, 23],
[31, 32, 33]])
Les tranches sont modifiables :
In [66]: # sauts
In [56]: A[1:3] = [-2,-3] A[::2, ::2]

A Out[66]: array([[ 0, 2, 4],


[20, 22, 24],
Out[56]: array([ 1, -2, -3, 4, 5]) [40, 42, 44]])

On peut omettre n'importe lequel des argument dans M[start:stop:step]:


Indexation avancée (fancy indexing)
In [57]: A[::] # indices de début, fin, et pas avec leurs valeurs par défaut
Lorsque qu'on utiliser des listes ou des array pour définir des tranches :
Out[57]: array([ 1, -2, -3, 4, 5])
In [67]: row_indices = [1, 2, 3]
A[row_indices]
In [58]: A[::2] # pas = 2, indices de début et de fin par défaut
Out[67]: array([[10, 11, 12, 13, 14],
Out[58]: array([ 1, -3, 5]) [20, 21, 22, 23, 24],
[30, 31, 32, 33, 34]])
In [59]: A[:3] # les trois premiers éléments
In [76]: print A
Out[59]: array([ 1, -2, -3])
print A[[1, 2], [3, 4]]
print A[[1, 2]][:, [3, 4]] where
print A[np.ix_([1, 2], [3, 4])] Un masque binaire peut être converti en indices de positions avec where
[[ 0 1 2 3 4]
[10 11 12 13 14] In [70]: x = arange(0, 10, 0.5)
[20 21 22 23 24] print x
[30 31 32 33 34] mask = (x > 5) * (x < 7.5)
[40 41 42 43 44]] indices = where(mask)
[13 24]
[[13 14] indices
[23 24]]
[ 0. 0.5 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5
[[13 14]
7.
[23 24]]
7.5 8. 8.5 9. 9.5]
Out[70]: (array([11, 12, 13, 14]),)
In [78]: A[[1, 2]][:, [3, 4]] = 0 # ATTENTION !
print A
In [71]: x[indices] # équivalent à x[mask]
[[ 0 1 2 3 4]
[10 11 12 13 14] Out[71]: array([ 5.5, 6. , 6.5, 7. ])
[20 21 22 23 24]
[30 31 32 33 34]
diag
[40 41 42 43 44]]
Extraire la diagonale ou une sous-diagonale d'un array :

In [79]: A[np.ix_([1, 2], [3, 4])] = 0


In [72]: print A
print A
diag(A)
[[ 0 1 2 3 4]
[[ 0 1 2 3 4]
[10 11 12 0 0]
[10 11 12 13 14]
[20 21 22 0 0]
[20 21 22 23 24]
[30 31 32 33 34]
[30 31 32 33 34]
[40 41 42 43 44]]
[40 41 42 43 44]]
Out[72]: array([ 0, 11, 22, 33, 44])
In [68]: col_indices = [1, 2, -1] # rappel : l'indice -1 fait référence au
dernier élément
A[row_indices, col_indices] In [73]: diag(A, -1)

Out[68]: array([11, 22, 34]) Out[73]: array([10, 21, 32, 43])

On peut aussi utiliser des masques binaires : take


take permet aussi de faire de l'indexation avancée :
In [67]: B = arange(5)
B In [74]: v2 = arange(-3,3)
v2
Out[67]: array([0, 1, 2, 3, 4])
Out[74]: array([-3, -2, -1, 0, 1, 2])
In [68]: row_mask = array([True, False, True, False, False])
B[row_mask] In [75]: row_indices = [1, 3, 5]
v2[row_indices] # fancy indexing
Out[68]: array([0, 2])
Out[75]: array([-2, 0, 2])
In [69]: # de façon équivalente
row_mask = array([1,0,1,0,0], dtype=bool) In [76]: v2.take(row_indices)
B[row_mask]
Out[76]: array([-2, 0, 2])
Out[69]: array([0, 2])
Mais take fonctionnne aussi sur d'autres types d'objets :

Extraction de données à partir d'arrays et création d'arrays In [77]: take([-3, -2, -1, 0, 1, 2], row_indices)
Out[77]: array([-2, 0, 2])

In [89]: A * 2, A + 2
choose
Construire un array en selectionnant des éléments dans d'autres arrays :
Out[89]: (array([[ 0, 2, 4, 6, 8],
[20, 22, 24, 0, 0],
In [78]: which = [1, 0, 1, 0]
[40, 42, 44, 0, 0],
choices = [[-2,-2,-2,-2], [5,5,5,5]]
[60, 62, 64, 66, 68],
[80, 82, 84, 86, 88]]),
choose(which, choices)
array([[ 2, 3, 4, 5, 6],
[12, 13, 14, 2, 2],
Out[78]: array([ 5, -2, 5, -2]) [22, 23, 24, 2, 2],
[32, 33, 34, 35, 36],
[42, 43, 44, 45, 46]]))
Algèbre linéaire
La performance des programmes écrit en Python/Numpy dépend de la capacité à vectoriser les calculs (les Visualiser des matrices
écrire comme des opérations sur des vecteurs/matrices) en évitant au maximum les boucles for/while

In [90]: C = random.rand(300,200)
Opérations scalaires figure()
On peut effectuer les opérations arithmétiques habituelles pour multiplier, additionner, soustraire et diviser des imshow(C)
arrays avec/par des scalaires : colorbar()
show()
In [85]: v1 = arange(0, 5)

In [86]: v1 * 2

Out[86]: array([0, 2, 4, 6, 8])

In [87]: v1 + 2

Out[87]: array([2, 3, 4, 5, 6])

In [88]: figure()
subplot(1,2,1)
plot(v1 ** 2,'g--', label='$y = x^2$')
legend(loc=0)
subplot(1,2,2)
plot(sqrt(v1), 'r*-', label='$y = \sqrt{x}$')
legend(loc=2)
show() Opérations terme-à-terme sur les arrays
Les opérations par défaut sont des opérations terme-à-terme :

In [91]: A * A # multiplication terme-à-terme

Out[91]: array([[ 0, 1, 4, 9, 16],


[ 100, 121, 144, 0, 0],
[ 400, 441, 484, 0, 0],
[ 900, 961, 1024, 1089, 1156],
[1600, 1681, 1764, 1849, 1936]])

In [92]: v1 * v1

Out[92]: array([ 0, 1, 4, 9, 16])


En multipliant des arrays de tailles compatibles, on obtient des multiplications terme-à-terme par ligne :
In [97]: A.dot(v1)
In [93]: A.shape, v1.shape
Out[97]: array([ 30, 35, 65, 330, 430])
Out[93]: ((5, 5), (5,))
In [91]: dot(v1, v1)
In [94]: print A
print v1 Out[91]: 30
A * v1

[[ 0 1 2 3 4] In [98]: M = matrix(A)
[10 11 12 0 0] v = matrix(v1).T # en faire un vecteur colonne
[20 21 22 0 0]
[30 31 32 33 34] In [103]: v, v.T
[40 41 42 43 44]]
[0 1 2 3 4] Out[103]: (matrix([[0],
Out[94]: array([[ 0, 1, 4, 9, 16], [1],
[ 0, 11, 24, 0, 0], [2],
[ 0, 21, 44, 0, 0], [3],
[ 0, 31, 64, 99, 136], [4]]),
[ 0, 41, 84, 129, 176]]) matrix([[0, 1, 2, 3, 4]]))

In [106]: v1, v1.T


Exercice:
Sans utiliser de boucles (for/while) : Out[106]: (array([0, 1, 2, 3, 4]), array([0, 1, 2, 3, 4]))

Créer une matrice (5x6) aléatoire In [114]: v1, v1.reshape((5, 1)).T


Remplacer une colonne sur deux, sauf la dernière colonne, par sa valeur moins le double de la
print v1.reshape((5, 1)).T
colonne suivante
print v1.reshape((5, 1)).T[0]
Remplacer les valeurs négatives par 0 en utilisant un masque binaire
[[0 1 2 3 4]]
[0 1 2 3 4]
Algèbre matricielle
In [124]: print dot(v1, v1)
Comment faire des multiplications de matrices ? Deux façons : print sum(v1 * v1)
print (v1 * v1).sum()
en utilisant les fonctions dot; print v1
en utiliser le type matrix. v1
print "%s" % v1,
print 1
In [95]: print dot(A, A)
print A * A 30
print type(A) 30
30
[[ 300 310 320 271 278] [0 1 2 3 4]
[ 350 383 416 30 40] [0 1 2 3 4] 1
[ 650 713 776 60 80]
[3300 3460 3620 2641 2738]
In [102]: print M*M
[4300 4510 4720 3431 3558]]
print dot(M, M)
[[ 0 1 4 9 16]
[ 100 121 144 0 0] [[ 300 310 320 271 278]
[ 400 441 484 0 0] [ 350 383 416 30 40]
[ 900 961 1024 1089 1156] [ 650 713 776 60 80]
[1600 1681 1764 1849 1936]] [3300 3460 3620 2641 2738]
<type 'numpy.ndarray'> [4300 4510 4720 3431 3558]]
[[ 300 310 320 271 278]
In [96]: dot(A, v1) [ 350 383 416 30 40]
[ 650 713 776 60 80]
Out[96]: array([ 30, 35, 65, 330, 430]) [3300 3460 3620 2641 2738]
[4300 4510 4720 3431 3558]]
Plus haut .T a été utilisé pour transposer l'objet matrice v
In [95]: M*v On peut aussi utiliser la fonction transpose

Out[95]: matrix([[ 30], Autres transformations :


[130],
[230], In [101]: C = matrix([[1j, 2j], [3j, 4j]])
[330], C
[430]])
Out[101]: matrix([[ 0.+1.j, 0.+2.j],
[ 0.+3.j, 0.+4.j]])
In [96]: # produit scalaire
v.T * v
In [102]: conjugate(C)
Out[96]: matrix([[30]])
Out[102]: matrix([[ 0.-1.j, 0.-2.j],
[ 0.-3.j, 0.-4.j]])
In [97]: # avec les objets matrices, c'est les opérations standards sur les
matrices qui sont appliquées
Transposée conjuguée :
v + M*v

Out[97]: matrix([[ 30], In [103]: C.H


[131],
[232], Out[103]: matrix([[ 0.-1.j, 0.-3.j],
[333], [ 0.-2.j, 0.-4.j]])
[434]])
Parties réelles et imaginaires :
Si les dimensions sont incompatibles on provoque des erreurs :
In [104]: real(C) # same as: C.real
In [98]: v = matrix([1,2,3,4,5,6]).T
Out[104]: matrix([[ 0., 0.],
[ 0., 0.]])
In [99]: shape(M), shape(v)

Out[99]: ((5, 5), (6, 1)) In [105]: imag(C) # same as: C.imag

Out[105]: matrix([[ 1., 2.],


In [100]: M * v [ 3., 4.]])

----------------------------------------------------------------------- Argument et module :


----
ValueError Traceback (most recent call In [106]: angle(C+1)
last)
<ipython-input-100-995fb48ad0cc> in <module>() Out[106]: array([[ 0.78539816, 1.10714872],
----> 1 M * v [ 1.24904577, 1.32581766]])
/Library/Frameworks/Python.framework/Versions/7.2/lib/python2.7/site-
packages/numpy/matrixlib/defmatrix.pyc in __mul__(self, other) In [107]: abs(C)
328 if isinstance(other,(N.ndarray, list, tuple)) :
329 # This promotes 1-D vectors to row vectors Out[107]: matrix([[ 1., 2.],
--> 330 return N.dot(self, asmatrix(other)) [ 3., 4.]])
331 if isscalar(other) or not hasattr(other, '__rmul__') :
332 return N.dot(self, other)
Caclul matriciel
ValueError: objects are not aligned

Voir également les fonctions : inner, outer, cross, kron, tensordot. Utiliser par exemple help(kron).
Analyse de données

Transformations d'arrays ou de matrices Numpy propose des fonctions pour calculer certaines statistiques des données stockées dans des arrays :

In [131]: data = np.vander([1, 2, 3, 4])


print data
print data.shape In [116]: # produit des éléments
prod(d+1)
[[ 1 1 1 1]
[ 8 4 2 1] Out[116]: 3628800
[27 9 3 1]
[64 16 4 1]]
(4, 4) In [117]: # somme cumulée
cumsum(d)
mean
Out[117]: array([ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45])
In [132]: # la moyenne de la troisième colonne
mean(data[:,2]) In [118]: # produit cumulé
cumprod(d+1)
Out[132]: 1.0
Out[118]: array([ 1, 2, 6, 24, 120, 720, 5040,
variance et écart type 40320, 362880, 3628800])

In [134]: var(data[:,2]), std(data[:,2])


In [140]: # équivalent à diag(A).sum()
trace(data)
Out[134]: (1.25, 1.1180339887498949)
Out[140]: 9
min et max

In [136]: data[:,2].min()
Calculs avec parties d'arrays
Out[136]: 1 en utilisant l'indexation ou n'importe quelle méthode d'extraction de donnés à partir des arrays

In [137]: data[:,2].max() In [120]: data

Out[137]: 4 Out[120]: array([[ 1., 2., 3., 4., 5.],


[ 6., 7., 8., 9., 10.],
[ 1., 3., 3., 4., 6.],
In [138]: data[:,2].sum() [ 1., 2., 3., 4., 20.]])

Out[138]: 10
In [121]: unique(data[:,1])

In [139]: data[:,2].prod() Out[121]: array([ 2., 3., 7.])

Out[139]: 24
In [122]: mask = data[:,1] == 2
sum, prod, et trace
In [123]: mean(data[mask,3])
In [113]: d = arange(0, 10)
d Out[123]: 4.0

Out[113]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])


Calculs aves données multi-dimensionnelles
In [114]: # somme des éléments
Pour appliquer min, max, etc., par lignes ou colonnes :
sum(d)

Out[114]: 45 In [145]: m = rand(3,4)


m
ou encore :
Out[145]: array([[ 0.03698607, 0.12245731, 0.3050354 , 0.49168305],
[ 0.62292662, 0.01005386, 0.55111996, 0.22627864],
In [115]: d.sum()
[ 0.93513639, 0.52761365, 0.81707137, 0.55497727]])
Out[115]: 45
In [146]: # max global
In [146]: # max global
m.max() In [161]: A # A est aussi modifié !

Out[146]: 0.9351363920751693 Out[161]: array([[10, 2],


[ 3, 4]])

In [147]: # max dans chaque colonne


m.max(axis=0) In [168]: print A - A[:,0] # FAUX
print A - A[:,0].reshape((2, 1)) # OK
Out[147]: array([ 0.93513639, 0.52761365, 0.81707137, 0.55497727]) [[ 0 -1]
[-7 1]]
In [148]: # max dans chaque ligne [[ 0 -8]
m.max(axis=1) [ 0 1]]

Out[148]: array([ 0.49168305, 0.62292662, 0.93513639])


Changement de forme et de taille, et concaténation des arrays
Plusieurs autres méthodes des classes array et matrix acceptent l'argument (optional) axis keyword
argument.
In [135]: A

Copy et "deep copy" Out[135]: array([[10, 2],


[ 3, 4]])
Pour des raisons de performance Python ne copie pas automatiquement les objets (par exemple passage par
référence des paramètres de fonctions).
In [136]: n, m = A.shape
In [154]: A = array([[0, 2],[ 3, 4]])
A In [137]: B = A.reshape((1,n*m))
B
Out[154]: array([[0, 2],
[3, 4]]) Out[137]: array([[10, 2, 3, 4]])

In [155]: B = A In [138]: B[0,0:5] = 5 # modifier l'array

B
In [156]: # changer B affecte A
B[0,0] = 10
Out[138]: array([[5, 5, 5, 5]])
B

Out[156]: array([[10, 2], In [139]: A


[ 3, 4]])
Out[139]: array([[5, 5],
[5, 5]])
In [157]: A

Out[157]: array([[10, 2],


[ 3, 4]]) Attention !
La variable originale est aussi modifiée ! B n'est qu'une nouvelle vue de A.
Pour éviter ce comportement, on peut demander une copie
profonde (deep
copy) de A dans B
Pour transformer un array multi-dimmensionel en un vecteur. Mais cette fois-ci, une copie des données est
In [159]: B = copy(A) créée :
B = A.copy()
In [140]: B = A.flatten()
B
In [160]: # maintenant en modifiant B, A n'est plus affecté
B[0,0] = -5 Out[140]: array([5, 5, 5, 5])

B
In [141]: B[0:5] = 10
Out[160]: array([[-5, 2], B
[ 3, 4]])
Out[141]: array([10, 10, 10, 10])

In [161]: A # A est aussi modifié !


In [142]: A # A ne change pas car B est une copie de A Pour répéter la matrice, il faut utiliser tile

Out[142]: array([[5, 5], In [151]: # répéter la matrice 3 fois


[5, 5]]) tile(a, 3)

Out[151]: array([[1, 2, 1, 2, 1, 2],


Ajouter une nouvelle dimension avec newaxis [3, 4, 3, 4, 3, 4]])

par exemple pour convertir un vecteur en une matrice ligne ou colonne : concatenate

In [143]: v = array([1,2,3]) In [152]: b = array([[5, 6]])

In [144]: shape(v) In [153]: concatenate((a, b), axis=0)

Out[144]: (3,) Out[153]: array([[1, 2],


[3, 4],
[5, 6]])
In [145]: # créer une matrice à une colonne à partir du vectuer v
v[:, newaxis]
In [154]: concatenate((a, b.T), axis=1)
Out[145]: array([[1],
[2], Out[154]: array([[1, 2, 5],
[3]]) [3, 4, 6]])

hstack et vstack
In [146]: v[:,newaxis].shape

Out[146]: (3, 1) In [155]: vstack((a,b))

Out[155]: array([[1, 2],


In [147]: # matrice à une ligne [3, 4],
v[newaxis,:].shape [5, 6]])

Out[147]: (1, 3)
In [156]: hstack((a,b.T))

Out[156]: array([[1, 2, 5],


Concaténer, répéter des arrays [3, 4, 6]])
En utilisant les fonctions repeat, tile, vstack, hstack, et concatenate, on peut créer des
vecteurs/matrices plus grandes à partir de vecteurs/matrices plus petites :

repeat et tile
Itérer sur les éléments d'un array
Dans la mesure du possible, il faut éviter l'itération sur les éléments d'un array : c'est beaucoup plus
In [148]: a = array([[1, 2], [3, 4]]) lent que les opérations vectorisées
a Mais il arrive que l'on n'ait pas le choix...

Out[148]: array([[1, 2],


[3, 4]]) In [157]: v = array([1,2,3,4])

In [149]: # répéter chaque élément 3 fois for element in v:


repeat(a, 3) # résultat 1-d print element

1
Out[149]: array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4]) 2
3
In [150]: # on peut spécifier l'argument axis 4
repeat(a, 3, axis=1)
In [158]: M = array([[1,2], [3,4]])
Out[150]: array([[1, 1, 1, 2, 2, 2],
[3, 3, 3, 4, 4, 4]]) for row in M:
print "row", row ----> 1 theta(array([-3,-2,-1,0,1,2,3]))

for element in row: <ipython-input-161-5cd8eb6ce61c> in theta(x)


print element 3 Scalar implemenation of the Heaviside step function.
4 """
row [1 2] ----> 5 if x >= 0:
1 6 return 1
2 7 else:
row [3 4]
3 ValueError: The truth value of an array with more than one element is
4 ambiguous. Use a.any() or a.all()
Pour obtenir les indices des éléments sur lesquels on itère (par exemple, pour pouvoir les modifier en même
temps) on peut utiliser enumerate :
erreur car la fonction theta n'a pas été conçue pour prendre des vecteurs en entrée
on peut utiliser la fonction vectorize :
In [159]: for row_idx, row in enumerate(M):
print "row_idx", row_idx, "row", row
In [163]: theta_vec = vectorize(theta)
for col_idx, element in enumerate(row):
print "col_idx", col_idx, "element", element
In [164]: theta_vec(array([-3,-2,-1,0,1,2,3]))
# update the matrix M: square each element
M[row_idx, col_idx] = element ** 2 Out[164]: array([0, 0, 0, 1, 1, 1, 1])

row_idx 0 row [1 2] Pour améliorer les performances, il vaut mieux concevoir dès le départ la fonction de sorte qu'elle accepte
col_idx 0 element 1 des vecteurs en entrée :
col_idx 1 element 2
row_idx 1 row [3 4]
In [165]: def theta(x):
col_idx 0 element 3
"""
col_idx 1 element 4
Vector-aware implementation of the Heaviside step function.
"""
In [160]: # chaque élément de M a maintenant été élevé au carré return 1 * (x >= 0)
M

Out[160]: array([[ 1, 4], In [166]: theta(array([-3,-2,-1,0,1,2,3]))


[ 9, 16]])
Out[166]: array([0, 0, 0, 1, 1, 1, 1])

Fonctions vectorisées In [167]: # toujours adapté à des scalaires


theta(-1.2), theta(2.6)
Comme on a intérêt à éviter les boucles, on peut définir des fonctions sur des vecteurs
Il faut d'abord s'assurer que de telles fonctions puissent gérer correctement des entrées vectorielles : Out[167]: (0, 1)

In [161]: def theta(x):


"""
Utilisation d'arrays dans des conditions
Scalar implemenation of the Heaviside step function.
Losqu'on s'intéresse à des conditions sur tout on une partie d'un array, on peut utiliser any ou all :
"""
if x >= 0:
return 1 In [168]: M
else:
return 0 Out[168]: array([[ 1, 4],
[ 9, 16]])

In [162]: theta(array([-3,-2,-1,0,1,2,3]))
In [169]: if (M > 5).any():
----------------------------------------------------------------------- print "au moins un élément de M est plus grand que 5"
---- else:
ValueError Traceback (most recent call print "aucun élément de M n'est plus grand que 5"
last) au moins un élément de M est plus grand que 5
<ipython-input-162-28c6d794452f> in <module>()
In [170]: if (M > 5).all():
print "tous les éléments de M sont plus grands que 5"
else:
print "tous les éléments de M sont plus petits que 5"

tous les éléments de M sont plus petits que 5

Type casting
On peut créer une vue d'un autre type que l'original pour un array

In [171]: M = array([[-1,2], [0,4]])


M.dtype

Out[171]: dtype('int32')

In [172]: M2 = M.astype(float)
M2

Out[172]: array([[-1., 2.],


[ 0., 4.]])

In [173]: M2.dtype

Out[173]: dtype('float64')

In [174]: M3 = M.astype(bool)
M3

Out[174]: array([[ True, True],


[False, True]], dtype=bool)

Pour aller plus loin


http://numpy.scipy.org
http://scipy.org/Tentative_NumPy_Tutorial
http://scipy.org/NumPy_for_Matlab_Users - Un guide pour les utilisateurs de MATLAB.

In []: