NumPy

Le module numpy permet le calcul numérique.

import matplotlib.pyplot as plt
import numpy as np

Matrice homogène

L’objet principal de NumPy est la matrice homogène multi-dimensionelle ndarray.

Voici d’abord une liste Python traditionnelle.

y = [2, 4, 3, 6, 2]
plt.plot(y, 'o-');
../_images/numpy_3_0.png

Nous pouvons la transformer en tableau numpy avec la fonction np.array. Le type de l’objet est ndarray (numeric data array).

a = np.array(y)
type(a)
numpy.ndarray

Avec un tableau numpy nous pouvons faire des opérations (additions, multiplications).

plt.plot(a)
plt.plot(2-a)
plt.plot(2*a);
../_images/numpy_7_0.png

Les attributs

Une matrice numpy possède multiples attributs:

  • ndim le nombre de dimensions

  • shape la forme de la matrice

  • size le nombre d’éléments

  • dtype le type de donnée

  • itemsize la taille d’un élément en octets

Voici un simple tableau 2D.

a = np.array([[1, 2, 1], [3, 2, 1]])
a
array([[1, 2, 1],
       [3, 2, 1]])

Sa dimension est

a.ndim
2

Sa forme est

a.shape
(2, 3)

Sa taille est

a.size
6

Son type est

a.dtype
dtype('int64')

La taille d’un élément est 8 octets (entier à 64 bits).

a.itemsize
8

Créer une plage

La fonction np.arange crée une plage numérique, de 0 à n-1.

np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Ou une plage entre deux bornes.

np.arange(5, 10)
array([5, 6, 7, 8, 9])

Et également avec un incrément.

np.arange(10, 20, 2)
array([10, 12, 14, 16, 18])
y = np.arange(10)
plt.grid()
plt.plot(y, 'o');
../_images/numpy_26_0.png

Visualiser des plages

Nous allons utiliser les marqueurs pour visualiser la position des points dans range().

y = np.zeros(5)
plt.plot(range(5), y, 'o-', label='range(5)')
plt.plot(range(2, 7), y+1, 'o-', label='range(2, 7)')
plt.plot(range(0, 10, 2), y+2, 'o-', label=range(0, 10, 2))
plt.legend()
plt.ylim(-0.5, 5)
plt.box(True)
plt.gcf().set_size_inches(8, 3)
../_images/numpy_28_0.png

Distribution uniforme

Le module np.random contient des fonctions pour créer des valeurs aléatoires.
La fonction rand(n) retourne n valeurs aléatoires dans l’intervalle [0, 1].

n = 500
y = np.random.rand(n)
plt.plot(y, 'o');
../_images/numpy_30_0.png

Faisons un histogramme avec 10 récipients. En moyenne nous avons 50 valeurs dans chaque récipient. On reconnait une distribution uniforme.

plt.hist(y, 10);
plt.axhline(n/10, color='r');
../_images/numpy_32_0.png

Distribution normale

La fonction randn(n) retourne n valeurs avec une distribution normale.

y = np.random.randn(n)
plt.plot(y, 'o');
../_images/numpy_34_0.png
plt.hist(y, 20);
../_images/numpy_35_0.png

Opérations sur un vecteur

Nous pouvons effectuer des opérations sur un vecteur numpy.

plt.plot(y, 'g', 0.5*y+1, 'r');
../_images/numpy_37_0.png

Matrice 2D

Avec numpy nous pouvons créer facilement des matrices avec de nombres aléatoires avec la fonction randint.

a = np.random.randint(255, size=[24, 36])
plt.imshow(a, cmap='autumn')
plt.colorbar();
plt.axis('off')
(-0.5, 35.5, 23.5, -0.5)
../_images/numpy_39_1.png
plt.imshow(a, cmap='gray');
../_images/numpy_40_0.png

Changer de forme

Nous réarrangeons (reshape) 60 valeurs croissantes sous forme de matrices:

  • 10 x 6

  • 5 x 12

  • 10 x 6 transposé

y = np.arange(60)
plt.imshow(y.reshape(10, 6), cmap='gray')
plt.colorbar();
../_images/numpy_43_0.png
plt.imshow(y.reshape(5, 12), cmap='gray')
plt.colorbar();
../_images/numpy_44_0.png
plt.imshow(y.reshape(10, 6).T, cmap='gray')
plt.colorbar();
../_images/numpy_45_0.png

Valeurs uniques

Quand on choisit des valeurs aléatoires, certaines valeurs peuvent apparaitres plusieurs fois.

n = 20
y = np.random.randint(1, n, size=n)
y
array([ 2, 17,  4, 16, 12, 16,  3,  8, 16,  4,  5,  2,  9,  5, 13,  7, 17,
       17,  9, 12])

La fonction set retourne seulement des valeurs uniques et les met dans l’ordre.

set(y)
{2, 4, 5, 7, 9, 10, 11, 12, 13, 14, 15, 17, 19}

Le module numpy possède la fonction unique qui fait la même chose.

np.unique(y)
array([ 2,  4,  5,  7,  9, 10, 11, 12, 13, 14, 15, 17, 19])

Cette fonction permet aussi de retrouver les indices vers le tableau y original.

np.unique(y, return_index=True)
(array([ 2,  4,  5,  7,  9, 10, 11, 12, 13, 14, 15, 17, 19]),
 array([11,  1, 19,  4, 14,  0,  9, 10,  8,  3,  2, 16,  5]))

Elle permet aussi de compter le nombre de répétitions.

np.unique(y, return_counts=True)
(array([ 2,  4,  5,  7,  9, 10, 11, 12, 13, 14, 15, 17, 19]),
 array([1, 3, 1, 1, 3, 2, 1, 1, 1, 2, 2, 1, 1]))

Enregistrer des données

Voici un vecteur avec 5 valeurs

a = np.arange(5, dtype='int8')
a
array([0, 1, 2, 3, 4], dtype=int8)

Avec save nous pouvons enregistrer ces donnes dans un fichier avec l’extension .npy .

np.save('data.npy', a)

Avec load nous pouvons charger ces donnes depuis un fichier.

b = np.load('data.npy')
b
array([0, 1, 2, 3, 4], dtype=int8)

C’est un fichier binaire, qui n’est pas lisible pour l’humain (à part l’entête).

cat data.npy
�NUMPYv{'descr': '|i1', 'fortran_order': False, 'shape': (5,), }                                                            


Enregistrer sous forme de texte

Avec savetxt nous pouvons enregistrer ces donnes dans un fichier texte.

np.savetxt('data.txt', a)

Avec cat nous pouvons afficher son contenu.

cat data.txt
0.000000000000000000e+00
1.000000000000000000e+00
2.000000000000000000e+00
3.000000000000000000e+00
4.000000000000000000e+00

Si nous chargeons les donnes dans une variable, le format n’est plus int8.

b = np.loadtxt('data.txt')
b
array([0., 1., 2., 3., 4.])

Dans savetxt nous pouvons spécifier le format.

np.savetxt('data.csv', a, newline=',', fmt='%d')
cat data.csv
0,1,2,3,4,

Le fichier csv n’occupe seulement 10 octets. Les autres 10 fois plus.

ll data*
-rw-r--r--  1 raphael  staff   10  5 mar 07:09 data.csv
-rw-r--r--  1 raphael  staff  133  5 mar 07:02 data.npy
-rw-r--r--  1 raphael  staff  125  5 mar 07:09 data.txt