NumPy
La bibliothèque fondamentale du calcul scientifique en Python : des tableaux multidimensionnels rapides et une algèbre vectorielle complète. pandas, scikit-learn, matplotlib, PyTorch — presque tout l'écosystème data Python est construit dessus.
À quoi ça sert
NumPy introduit un nouveau type d'objet en Python : le ndarray (n-dimensional array). C'est un tableau de nombres stocké en mémoire compacte (comme en C), sur lequel on peut faire des opérations vectorisées — c'est-à-dire appliquées à tout le tableau en une seule instruction, plutôt qu'avec une boucle.
Résultat : ce qui prendrait une boucle Python lente devient une opération quasi-instantanée en NumPy.
- Tableaux 1D, 2D, ND — vecteurs, matrices, tenseurs.
- Opérations vectorisées — addition, multiplication élément par élément, opérations matricielles.
- Indexation puissante — slicing, indexation booléenne, indexation par tableau.
- Algèbre linéaire — produit matriciel, inversion, décomposition, valeurs propres.
- Statistiques de base — moyenne, écart-type, min, max, somme sur n'importe quel axe.
- Génération aléatoire — distributions classiques pour simulations et initialisation de modèles.
Une liste Python est flexible mais lente : chaque élément est un objet Python séparé en mémoire. Un tableau NumPy stocke les nombres côte à côte en mémoire compacte et exécute les opérations en C natif. Pour 1 million d'éléments, une somme NumPy est typiquement 50× plus rapide qu'une boucle Python.
Un exemple d'usage
Tu as les températures relevées sur 30 jours et tu veux calculer quelques statistiques, puis détecter les jours anormalement chauds :
import numpy as np
temperatures = np.array([
14, 15, 16, 18, 20, 22, 19, 17, 16, 15,
14, 15, 17, 20, 24, 27, 28, 26, 23, 21,
19, 18, 20, 22, 25, 28, 30, 31, 29, 26,
])
# Statistiques de base
print(temperatures.mean()) # 21.0
print(temperatures.std()) # 5.16…
print(temperatures.max()) # 31
# Convertir en Fahrenheit en une ligne (vectorisé)
fahrenheit = temperatures * 9 / 5 + 32
# Indexation booléenne : tous les jours > moyenne + 1 écart-type
seuil = temperatures.mean() + temperatures.std()
jours_chauds = temperatures[temperatures > seuil]
print(jours_chauds) # [27 28 26 25 28 30 31 29 26]
print(np.where(temperatures > seuil)) # indices
Aucune boucle dans ce code. temperatures * 9 / 5 + 32 applique
l'opération à chaque élément. temperatures > seuil
renvoie un tableau de booléens, qu'on utilise comme masque pour ne garder
que les jours chauds.
How-to : installer et utiliser NumPy
-
Installer NumPy
Dépendance principale (cf. UV) — mais le plus souvent NumPy s'installe automatiquement avec pandas, scikit-learn, matplotlib, etc., car ils en dépendent.
bashuv add numpyConvention universelle : importer sous l'alias
np.pythonimport numpy as np -
Créer un tableau
python# Depuis une liste a = np.array([1, 2, 3, 4]) # 2D : matrice (liste de listes) m = np.array([[1, 2], [3, 4]]) # Tableaux construits np.zeros((3, 4)) # matrice 3×4 de zéros np.ones(10) # vecteur de 1 np.arange(0, 10, 2) # [0 2 4 6 8] np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1.] # Aléatoire rng = np.random.default_rng(seed=42) rng.normal(loc=0, scale=1, size=(100,)) -
Inspecter un tableau
pythona.shape # (4,) ou (3, 4) selon la dimension a.ndim # nombre de dimensions a.size # nombre total d'éléments a.dtype # int64, float64, bool, … -
Indexer et slicer
Comme une liste Python, mais en plus puissant — y compris en 2D :
pythona = np.arange(10) # [0 1 2 ... 9] a[0] # 0 a[-1] # 9 a[2:5] # [2 3 4] a[::2] # [0 2 4 6 8] (un sur deux) # 2D : [ligne, colonne] m = np.arange(12).reshape(3, 4) m[0, 1] # élément ligne 0, colonne 1 m[:, 0] # toute la 1ère colonne m[1, :] # toute la 2e ligne # Indexation booléenne (très utile en data) data = np.array([3, 7, 2, 9, 4]) data[data > 5] # [7 9] -
Opérations vectorisées
Les opérateurs
+,-,*,/s'appliquent élément par élément :pythona = np.array([1, 2, 3]) b = np.array([10, 20, 30]) a + b # [11 22 33] a * 2 # [2 4 6] a ** 2 # [1 4 9] np.sqrt(a) # [1. 1.414 1.732] np.exp(a) # exponentielle # Produit matriciel (≠ multiplication élément par élément) A = np.array([[1, 2], [3, 4]]) B = np.array([[5, 6], [7, 8]]) A @ B # produit matriciel -
Agréger sur un axe
En 2D, on peut résumer ligne par ligne (
axis=1) ou colonne par colonne (axis=0) :pythonm = np.array([[1, 2, 3], [4, 5, 6]]) m.sum() # 21 (somme totale) m.sum(axis=0) # [5 7 9] (somme par colonne) m.sum(axis=1) # [6 15] (somme par ligne) m.mean(axis=0) # moyenne de chaque colonneMémoriser axis=0 et axis=1axis=0 = on agrège le long des lignes, donc on se déplace verticalement → résultat par colonne. axis=1 = on agrège le long des colonnes, donc on se déplace horizontalement → résultat par ligne. Quand tu hésites, fais un petit test avec
shape. -
Reshape et broadcasting
reshapechange la forme sans copier les données. Broadcasting = NumPy aligne automatiquement deux tableaux de formes compatibles pour faire l'opération :pythona = np.arange(12) # shape (12,) a.reshape(3, 4) # shape (3, 4) a.reshape(-1, 2) # -1 = calcule automatiquement # Broadcasting : ajouter un vecteur à chaque ligne d'une matrice m = np.array([[1, 2, 3], [4, 5, 6]]) # (2, 3) v = np.array([10, 20, 30]) # (3,) m + v # [[11 22 33] # [14 25 36]] -
Sauvegarder et charger
pythonnp.save("data.npy", a) # un tableau, format binaire a = np.load("data.npy") np.savetxt("data.csv", a, delimiter=",") np.loadtxt("data.csv", delimiter=",")En pratique, dès que les données ont des colonnes nommées ou des types mélangés, on préfère
pandas(qui produit/consomme des arrays NumPy en interne).
Aide-mémoire
np.array([1, 2, 3])
np.zeros((3, 4)), np.ones(5), np.eye(3)
np.arange(0, 10, 2), np.linspace(0, 1, 11)
rng = np.random.default_rng(42); rng.normal(size=10)
a[0], a[-1], a[2:5], a[::2]
m[0, 1], m[:, 0], m[1, :]
a[a > 5] # masque booléen
np.where(a > 5) # indices
a.mean(), a.std(), a.min(), a.max(), a.sum()
m.sum(axis=0), m.mean(axis=1)
A @ B # produit matriciel
np.linalg.inv(A), np.linalg.eig(A)
a.shape, a.ndim, a.size, a.dtype
a.reshape(3, 4), a.flatten()
np.concatenate([a, b]), np.stack([a, b])
NumPy et le reste de l'écosystème
NumPy n'est presque jamais utilisé seul : c'est la fondation
sur laquelle reposent les autres libs data. On le « voit » surtout au
moment du débogage (un df["x"].values renvoie un array NumPy).
-
pandas — un DataFrame est un
ensemble de Series, et chaque Series est un wrapper autour
d'un array NumPy.
df.valuesouseries.to_numpy()sort le tableau brut. -
matplotlib — tous les
plots prennent des arrays NumPy en entrée
(
ax.plot(x, y)avecx, ydes arrays). -
scikit-learn — les
modèles attendent des arrays NumPy 2D
X(samples × features) et 1Dy(labels). pandas convertit automatiquement. -
PyTorch — les tensors PyTorch sont
l'équivalent GPU des arrays NumPy.
torch.from_numpy(arr)ettensor.numpy()font la conversion sans copie quand c'est possible. -
Polars — utilise Apache Arrow
en interne plutôt que NumPy, mais accepte les conversions :
df.to_numpy()etpl.from_numpy(arr).
Si tes données sont tabulaires (colonnes nommées, types mélangés), passe par pandas — c'est plus lisible. Tu utilises NumPy directement pour : du calcul purement numérique (simulations, traitement d'image, algèbre linéaire), implémenter un algorithme à la main, ou pour des perfs maximales sur de gros vecteurs homogènes.
Pour aller plus loin
- Site officiel : numpy.org
- « NumPy: the absolute basics for beginners » : numpy.org/doc/stable/user/absolute_beginners.html
- Référence API : numpy.org/doc/stable/reference
- « From Python to NumPy » (livre libre, Nicolas Rougier) : labri.fr/perso/nrougier/from-python-to-numpy