Premiers pas en numpy


Auteur: Joseph Salmon

[email protected]

In [1]:
import numpy as np
np.__version__
Out[1]:
'1.16.2'
In [2]:
import matplotlib.pyplot as plt
In [3]:
np.set_printoptions(precision=2) # pour fixer le nombre de digits affichés

Génération d'arrays à partir de listes

In [4]:
# un vecteur: l'argument de la fonction est une liste Python
liste = [1, 3, 2, 4]
vecteur = np.array(liste)
print(vecteur)
[1 3 2 4]
In [5]:
# une matrice: l'argument est une liste emboitée
matrice = np.array([[1, 2], [3, 4]])
print(matrice)
print(matrice[0,0])
print(matrice[0,1])
[[1 2]
 [3 4]]
1
2
In [6]:
tenseur = np.array([[[1, 2], [3, 4]],
                    [[21, 21], [23, 34]]])
print(tenseur)
[[[ 1  2]
  [ 3  4]]

 [[21 21]
  [23 34]]]
In [7]:
type(vecteur), type(matrice), type(tenseur)
Out[7]:
(numpy.ndarray, numpy.ndarray, numpy.ndarray)
In [8]:
np.shape(vecteur), matrice.shape, tenseur.shape
Out[8]:
((4,), (2, 2), (2, 2, 2))
In [9]:
matrice_cpx = np.array([[1, 2], [3, 4]], dtype=complex)
matrice_cpx
Out[9]:
array([[1.+0.j, 2.+0.j],
       [3.+0.j, 4.+0.j]])

Génération d'arrays à partir de fonctions

In [10]:
x = np.arange(0, 10, 2) # arguments: start, stop, step
x
Out[10]:
array([0, 2, 4, 6, 8])
In [11]:
y = np.arange(-1, 1, 0.5)
y
Out[11]:
array([-1. , -0.5,  0. ,  0.5])
In [12]:
print(x.dtype, y.dtype)
int64 float64

linspace:

In [13]:
# avec linspace, le début et la fin SONT inclus
np.linspace(0, 5, 11)
Out[13]:
array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ])

logspace:

In [14]:
np.logspace(0, 11, 10)
Out[14]:
array([1.00e+00, 1.67e+01, 2.78e+02, 4.64e+03, 7.74e+04, 1.29e+06,
       2.15e+07, 3.59e+08, 5.99e+09, 1.00e+11])
In [15]:
10**(np.linspace(np.log10(1), np.log10(10**11), 10))
Out[15]:
array([1.00e+00, 1.67e+01, 2.78e+02, 4.64e+03, 7.74e+04, 1.29e+06,
       2.15e+07, 3.59e+08, 5.99e+09, 1.00e+11])

diag : première utilisation

In [16]:
np.diag([1, 2, 3], k=0)
Out[16]:
array([[1, 0, 0],
       [0, 2, 0],
       [0, 0, 3]])
In [17]:
np.diag([1, 2, 3], k=1)
Out[17]:
array([[0, 1, 0, 0],
       [0, 0, 2, 0],
       [0, 0, 0, 3],
       [0, 0, 0, 0]])
In [18]:
np.diag([1, 2, 3], k=1).T
Out[18]:
array([[0, 0, 0, 0],
       [1, 0, 0, 0],
       [0, 2, 0, 0],
       [0, 0, 3, 0]])
In [19]:
np.transpose(np.diag([1, 2, 3], k=1))
Out[19]:
array([[0, 0, 0, 0],
       [1, 0, 0, 0],
       [0, 2, 0, 0],
       [0, 0, 3, 0]])

diag : seconde utilisation

In [20]:
np.diag(np.diag([1, 2, 3], k=0))
Out[20]:
array([1, 2, 3])

zeros

In [21]:
np.zeros((3,), dtype=int)
Out[21]:
array([0, 0, 0])
In [22]:
print(np.zeros((3, 2), dtype=float))
print(np.zeros((1, 3), dtype=float))
print(np.zeros((3, 1), dtype=float))
[[0. 0.]
 [0. 0.]
 [0. 0.]]
[[0. 0. 0.]]
[[0.]
 [0.]
 [0.]]

ones

In [23]:
np.ones((3,3))
Out[23]:
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])

full

In [24]:
np.full((3, 5), 3.14)
Out[24]:
array([[3.14, 3.14, 3.14, 3.14, 3.14],
       [3.14, 3.14, 3.14, 3.14, 3.14],
       [3.14, 3.14, 3.14, 3.14, 3.14]])

eye

In [25]:
np.eye(3)
Out[25]:
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
In [26]:
np.eye(3, dtype=int)
Out[26]:
array([[1, 0, 0],
       [0, 1, 0],
       [0, 0, 1]])

Concaténation d'array

In [27]:
A = np.array([[0,  2],[ 3,  4]])
B = np.array([[1,  2],[ 5,  4]])
np.vstack((A,B))  # concaténation verticale
Out[27]:
array([[0, 2],
       [3, 4],
       [1, 2],
       [5, 4]])
In [28]:
np.hstack((A,B))  # concaténation horizontale
Out[28]:
array([[0, 2, 1, 2],
       [3, 4, 5, 4]])

Fonctions sur les lignes / colonnes:

mean (en français 'moyenne')

In [29]:
np.mean(A)
Out[29]:
2.25
In [30]:
np.mean(B,axis=0)  # moyenne des colonnes
Out[30]:
array([3., 3.])
In [31]:
np.mean(B,axis=1)  # moyenne des lignes
Out[31]:
array([1.5, 4.5])

sum (en français 'somme')

In [32]:
np.sum(A)
Out[32]:
9
In [33]:
np.sum(A, axis=0) # somme en colonne
Out[33]:
array([3, 6])
In [34]:
np.sum(A, axis=1) # somme en ligne
Out[34]:
array([2, 7])

cumsum (en français 'sommes cumulées')

In [35]:
np.cumsum(A)  # noter l'ordre en ligne
Out[35]:
array([0, 2, 5, 9])
In [36]:
np.cumsum(A, axis=0)  # somme cumulée en colonne
Out[36]:
array([[0, 2],
       [3, 6]])
In [37]:
np.cumsum(A, axis=1)  # somme cumulée en ligne
Out[37]:
array([[0, 2],
       [3, 7]])

Note: il existe la même chose avec prod et cumprod pour le produit au lieu de l'addition.

Slicing

Comme pour les string que l'on a déjà vu, le slicing est disponible pour les arrays, avec en plus la possibilité d'y avoir accès pour chaque dimension:

In [38]:
A[:, 0]  # accès à la première colonne
Out[38]:
array([0, 3])
In [39]:
A[1, :]  # accès à la deuxième ligne
Out[39]:
array([3, 4])

Il est aussi utile de travailler avec des masques:

In [40]:
print(A < 2)
print(A[A < 2])
A[A < 2]= 0.
print(A)  # met à zéro tous les termes plus petit que 2
[[ True False]
 [False False]]
[0]
[[0 2]
 [3 4]]

Vectorisation des operations

In [41]:
2**A
Out[41]:
array([[ 1,  4],
       [ 8, 16]])
In [42]:
 A**3
Out[42]:
array([[ 0,  8],
       [27, 64]])
In [43]:
A + 1
Out[43]:
array([[1, 3],
       [4, 5]])
In [44]:
np.exp(A)
Out[44]:
array([[ 1.  ,  7.39],
       [20.09, 54.6 ]])
In [45]:
from scipy.linalg import expm
expm(A)
Out[45]:
array([[ 32.33,  55.1 ],
       [ 82.65, 142.54]])

Mutliplication matricielle:

In [46]:
A @ B
Out[46]:
array([[10,  8],
       [23, 22]])
In [47]:
A.dot(B)
Out[47]:
array([[10,  8],
       [23, 22]])
In [48]:
np.dot(A, B)
Out[48]:
array([[10,  8],
       [23, 22]])

Génération aléatoire

rand : la loi uniforme sur $[0,1]$

In [49]:
np.random.rand(5, 5)  # nombres aléatoire entre 0. et 1.
Out[49]:
array([[0.74, 0.81, 0.52, 0.39, 0.78],
       [0.25, 0.09, 0.93, 0.5 , 0.4 ],
       [0.5 , 0.14, 0.93, 0.08, 0.73],
       [0.83, 0.87, 0.72, 0.74, 0.16],
       [0.37, 0.72, 0.31, 0.91, 0.29]])
In [50]:
np.random.rand(5, )  # un deuxième tirage
Out[50]:
array([0.76, 0.77, 0.05, 0.65, 0.34])
In [51]:
np.random.seed(2018)
np.random.rand(5, )  # un premier tirage aléatoire
Out[51]:
array([0.88, 0.1 , 0.91, 0.31, 0.45])
In [52]:
np.random.seed(2018)
np.random.rand(5, )  # un tirage identique.
Out[52]:
array([0.88, 0.1 , 0.91, 0.31, 0.45])

randn : la loi normale/gaussienne:

In [53]:
from scipy.stats import norm  # module loi normale

a = np.random.randn(10000)
x = np.linspace(-4, 4, 100)

# Affichage d'un histogramme normalisé avec matplotlib
fig = plt.figure(figsize=(8, 5))
hitogramme = plt.hist(a, bins=50, density=True)

# Oublier les détails matplotlib et Latex dans un premier temps
plt.plot(x, norm.pdf(x), linewidth=3, color='black',
         label=r"$\frac{1}{\sqrt{2\pi}} \cdot \exp\left(-\frac{x^2}{2}\right)$")
plt.xlabel("x")
plt.ylabel("Proportion")
plt.legend()
plt.show()
saving = False
if saving is True:
    fig.savefig("../prebuiltimages/gaussian.pdf")

Génération par importation de données

In [54]:
from download import download 
In [55]:
# pip install download # si besoin, décommenter et exécuter cette cellule.
In [56]:
pwd  # unix command "print working directory"
Out[56]:
'/home/jo/Documents/Mes_cours/Montpellier/HLMA310/Poly/codes'
In [57]:
url = "http://josephsalmon.eu/enseignement/datasets/data_test.csv"
path_target = "./data_set.csv"
download(url, path_target, replace=False)
file_sizes: 100%|████████████████████████████| 30.0/30.0 [00:00<00:00, 16.2kB/s]
Downloading data from http://josephsalmon.eu/enseignement/datasets/data_test.csv (30 bytes)

Successfully downloaded file to ./data_set.csv

Out[57]:
'./data_set.csv'
In [58]:
!cat data_set.csv # permet de lancer la commande unix cat pour visualiser le fichier
1,2,3,4,5
6,7,8,9,10
1,3,3,4,6
In [59]:
!cat data_set.csv # dans un notebook la commande cat fonctionne aussi
1,2,3,4,5
6,7,8,9,10
1,3,3,4,6

Note: d'autres fonctions unix sont disponibles en plus de pwd et cat:

  • cd : pour changer de dossier ( change directory en anglais)
  • cp : pour copy des fichiers ( copy en anglais)
  • ls : pour lister les fichiers à l'endroit courant ( list en anglais)
  • man : pour avoir accès au manuel/aide ( manual en anglais)
  • mkdir : pour créer un dossier ( make directory en anglais)
  • mv : pour déplacer un fichier ( move en anglais)
  • rm : pour supprimer un fichier ( remove en anglais)
  • rmdir : pour supprimer un dossier ( remove directory en anglais)
  • etc.
In [60]:
data_as_array = np.genfromtxt('data_set.csv', delimiter=',')
data_as_array
Out[60]:
array([[ 1.,  2.,  3.,  4.,  5.],
       [ 6.,  7.,  8.,  9., 10.],
       [ 1.,  3.,  3.,  4.,  6.]])

Export sous divers formats:

In [61]:
np.savetxt("random_matrix.txt", data_as_array)
In [62]:
!cat random_matrix.txt
1.000000000000000000e+00 2.000000000000000000e+00 3.000000000000000000e+00 4.000000000000000000e+00 5.000000000000000000e+00
6.000000000000000000e+00 7.000000000000000000e+00 8.000000000000000000e+00 9.000000000000000000e+00 1.000000000000000000e+01
1.000000000000000000e+00 3.000000000000000000e+00 3.000000000000000000e+00 4.000000000000000000e+00 6.000000000000000000e+00

Le format le plus courant pour sauvegarder un array est le format 'npy':

In [63]:
np.save("random_matrix.npy", data_as_array)

Pour charger un tel fichier il suffit alors de faire:

In [64]:
data_as_array2 = np.load("random_matrix.npy")
data_as_array2
Out[64]:
array([[ 1.,  2.,  3.,  4.,  5.],
       [ 6.,  7.,  8.,  9., 10.],
       [ 1.,  3.,  3.,  4.,  6.]])
In [ ]:
 

Effacer le fichier après usage si l'on ne s'en sert plus:

In [65]:
!rm data_set.csv
!rm random_matrix.txt
!rm random_matrix.npy

Note: la fonction rm vient de l'anglais remove (en français 'supprimer')

Copie / copie profonde (deep copy)

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 [66]:
A = np.array([[0,  2],[ 3,  4]])
B = A

Changer B va maintenant affecter A

In [67]:
B[0,0] = 10
B
Out[67]:
array([[10,  2],
       [ 3,  4]])
In [68]:
print(A)
print(B is A)  # les deux objets sont les mêmes
[[10  2]
 [ 3  4]]
True

Pour éviter ce comportement, on peut demander une copie profonde (deep copy en anglais) de A dans B:

In [69]:
B = A.copy()
In [70]:
B[0,0] = 111
B
Out[70]:
array([[111,   2],
       [  3,   4]])
In [71]:
A  # A n'est alors plus modifié car on a créé une copie de l'objet!
Out[71]:
array([[10,  2],
       [ 3,  4]])

Tests entre arrays

In [72]:
A == B
Out[72]:
array([[False,  True],
       [ True,  True]])
In [73]:
np.allclose(A,A+0.001)
Out[73]:
False
In [74]:
np.allclose(A,A+0.001, atol=0.01)
Out[74]:
True
In [ ]: