🔢 NumPy – Le Calcul Numérique Fondamental
Guide complet IDEO-Lab : ndarray, Indexing, Vectorization, Broadcasting & axis.
Vue d'ensemble
Numerical Python. Le socle de la Data Science (Pandas, Scikit).
Calcul Scientifique PythonPourquoi NumPy ? (Perf)
Performance (C), Vectorisation (pas de boucle), Mémoire (dtype).
Installation
pip install numpy. Convention : import numpy as np.
Concept N°1 : ndarray
L'objet central. Tableau N-D, type homogène. .shape, .dtype.
Création d'Arrays
np.array(), np.arange(), np.zeros(), np.linspace().
Indexing & Slicing
Syntaxe [start:stop:step]. 2D : arr[row, col].
Fancy Indexing (Masque)
arr[arr > 0]. Sélection via un masque booléen.
Fancy Indexing (Index)
arr[[0, 5, 2]]. Sélection via une liste d'index.
Concept N°2 : Vectorisation
Opérations +, *... (Element-wise). Pas de boucle for.
Concept N°3 : Broadcasting
Règles d'opérations sur des shapes différentes (ex: (3,3) + (3,)).
Agrégations
np.sum(), np.mean(), np.std(), np.max(), np.argmin().
🎛️ L'argument axis
axis=0 (vertical), axis=1 (horizontal). (Clé de l'agrégation).
Manipulation (Shape)
.reshape(r, c), .T (Transpose), .flatten().
Algèbre Linéaire (@)
@ (Matmul) (np.dot). np.linalg (inv, det).
Ufuncs (Fonctions Universelles)
np.sin(), np.exp(), np.log(). (Vectorisées).
Gestion des NaN
np.nan. np.isnan(), np.nansum(), np.nanmean().
Vitrine (L'Écosystème)
Fondation de Pandas, Scikit-learn, PyTorch, TensorFlow, Matplotlib...
Pandas Scikit-learnLiens Utiles & Formation
numpy.org (Docs), Tutoriels, API Reference.
NumPy vs Pandas
NumPy (Calcul brut, 1 dtype) vs Pandas (Analyse, multi-dtype, index).
Cheat-sheet
Syntaxe (Création, Slicing, Mask, Axis).
cheat SyntaxeQu'est-ce que NumPy ?
NumPy (Numerical Python) est LE **paquet fondamental** pour le calcul scientifique en Python.
Il fournit un objet central : le ndarray (N-dimensional array), un tableau multi-dimensionnel haute performance, et des outils pour l'utiliser.
C'est la "brique" sur laquelle **tout l'écosystème Data Science (PyData)** est construit.
Diagramme : La Fondation de l'Écosystème
+------------------+ +------------------+
| Matplotlib | | Scikit-learn | (ML)
+------------------+ +------------------+
^ ^
| (Consomme) | (Consomme .values)
+----------------------------------------+
| Pandas (DataFrame) | (Analyse)
+----------------------------------------+
^
| (Construit sur)
+----------------------------------------+
| NumPy (ndarray) | (Le Socle)
+----------------------------------------+
Le Problème (Listes Python)
Les listes Python sont flexibles (multi-types) mais **lentes** (interprétées) et **inefficaces** (mémoire).
// (Python pur: Boucle 'for' explicite)
// (Lent, coûteux en 'overhead' Python)
l1 = [1, 2, 3]
l2 = [4, 5, 6]
result = []
for i in range(len(l1)):
result.append(l1[i] + l2[i])
La Solution (Vectorisation & C)
1. Vectorisation : NumPy effectue les opérations (+, *) de manière "element-wise" (élément par élément) sans boucle for Python.
2. Performance (C) : Les boucles sont effectuées en langage C compilé (rapide).
3. Efficacité Mémoire : Un ndarray a un type **homogène** (ex: int64). Les données sont stockées de manière contiguë en mémoire.
// (NumPy: Vectorisé) // (Rapide, la boucle est en C) a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) result = a + b // result = [5, 7, 9]
L'installation se fait via pip ou conda. (Un environnement virtuel Python venv est fortement recommandé).
# 1. Installation (via pip) pip install numpy # 2. Installation (via Conda) conda install -c anaconda numpy
Import (Convention)
L'alias np est la convention universelle (tout comme pd pour Pandas).
import numpy as np print(np.__version__)
ndarrayL'ndarray est un conteneur N-dimensionnel (Array) pour des types **homogènes** (ex: que des float64).
Ses attributs (.) sont essentiels :
arr_2d = np.array(
[[1, 2, 3], [4, 5, 6]],
dtype=np.float32
)
// Attributs
print(arr_2d.shape) // (2, 3) (2 lignes, 3 colonnes)
print(arr_2d.ndim) // 2 (2 dimensions)
print(arr_2d.dtype) // float32
print(arr_2d.size) // 6 (Nombre total d'éléments)
print(arr_2d.itemsize) // 4 (Nb d'octets par élément, 32bits/8=4)
Depuis des listes
// 1D arr_1d = np.array([1, 2, 3]) // 2D (Matrice) arr_2d = np.array([[1, 2], [3, 4]])
Routines de création
// 1. Séquences arr_seq = np.arange(0, 10, 2) // (Start, Stop, Step) // [0, 2, 4, 6, 8] // 2. Linéaire arr_lin = np.linspace(0, 1, 5) // (Start, Stop, Nb points) // [0. , 0.25, 0.5 , 0.75, 1. ]
Placeholders (Formes)
// 1. Zéros (Shape 2x3) z = np.zeros((2, 3)) // 2. Uns o = np.ones((3, 2), dtype=np.int16) // 3. Aléatoire (Uniforme [0, 1]) r = np.random.rand(2, 2) // 4. Aléatoire (Normal/Gaussien) n = np.random.randn(2, 2)
L'accès aux données utilise la syntaxe [start:stop:step] (stop est exclusif).
Important : Les "Slices" (vues) NumPy ne sont **pas** des copies (contrairement aux listes Python). Modifier un slice modifie l'original (pour la performance). Utilisez .copy() pour une copie.
1D (Vecteur)
arr = np.arange(10) // [0, 1, ..., 9] arr[0] // 0 arr[2:5] // [2, 3, 4] arr[:5] // [0, 1, 2, 3, 4] arr[5:] // [5, 6, 7, 8, 9] arr[-1] // 9 (Dernier élément)
2D (Matrice)
Syntaxe : arr[row_slice, col_slice]
arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) // 1. Élément unique (Ligne 0, Col 1) arr_2d[0, 1] // 2 // 2. Ligne entière (Ligne 1, toutes les cols) arr_2d[1, :] // [4, 5, 6] // (Raccourci: arr_2d[1]) // 3. Colonne entière (Toutes les lignes, Col 0) arr_2d[:, 0] // [1, 4, 7] // 4. Sous-matrice arr_2d[0:2, 1:3] // [[2, 3], // [5, 6]]
C'est la méthode de filtrage la plus puissante. On passe un array booléen (le "masque") de même shape.
1. Créer le Masque
arr = np.array([1, 2, -5, 0, 8, -1]) // (1. Créer le masque (opération vectorisée)) mask = arr > 0 // [True, True, False, False, True, False] // 2. Appliquer le masque // (Retourne une *copie* des éléments où mask=True) result = arr[mask] // [1, 2, 8]
2. Conditions Multiples (&, |)
(Utiliser & (ET) et | (OU). Ne pas utiliser and/or. Parenthèses obligatoires).
mask_multi = (arr > 0) & (arr < 5) // [True, True, False, False, False, False] result_multi = arr[mask_multi] // [1, 2]
On peut passer une liste (ou un array) d'index pour sélectionner des éléments dans un ordre spécifique.
1D
arr = np.array([10, 20, 30, 40, 50]) index_list = [0, 2, 4] // (Sélectionne les index 0, 2, 4) result = arr[index_list] // [10, 30, 50]
2D
arr_2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) // (Sélectionne les lignes 0 et 2) result_rows = arr_2d[[0, 2]] // [[1, 2, 3], // [7, 8, 9]]
La vectorisation est l'art d'effectuer des opérations "element-wise" (élément par élément) sans écrire de boucle for Python. La boucle est effectuée en C.
Exemple (Python vs NumPy)
// Python (LENT)
list_a = [1, 2, 3]
list_b = [4, 5, 6]
result = []
for i in range(len(list_a)):
result.append(list_a[i] + list_b[i])
// result = [5, 7, 9]
// NumPy (RAPIDE)
arr_a = np.array([1, 2, 3])
arr_b = np.array([4, 5, 6])
result = arr_a + arr_b
// result = array([5, 7, 9])
// (Ceci s'applique à toutes les ops: +, -, *, /, **, ...)
result_mult = arr_a * arr_b
// result_mult = array([ 4, 10, 18])
Le Broadcasting est le mécanisme qui permet à NumPy d'effectuer des opérations sur des arrays de **shapes (formes) différentes**.
Règles (simplifiées) :
1. Si les rangs (ndim) diffèrent, le plus petit est "rembourré" (padded) avec des 1 à gauche. (ex: (3,) devient (1, 3)).
2. Les dimensions sont compatibles si : elles sont **égales** OU si l'une d'elles est **1**.
Diagramme ((3,3) + (3,))
A (3, 3) + B (3,)
[[1, 1, 1],
[2, 2, 2], [10, 20, 30]
[3, 3, 3]]
| (Règle 1: B (3,) -> (1, 3))
▼
A (3, 3) + B (1, 3)
[[1, 1, 1],
[2, 2, 2], [[10, 20, 30]]
[3, 3, 3]]
| (Règle 2: B (1,3) est "étiré" (broadcasté) en (3,3))
▼
A (3, 3) + B_broadcast (3, 3)
[[1, 1, 1], [[10, 20, 30],
[2, 2, 2], + [10, 20, 30],
[3, 3, 3]] [10, 20, 30]]
| (Opération Element-wise)
▼
Résultat (3, 3)
[[11, 21, 31],
[12, 22, 32],
[13, 23, 33]]
Réduire un array à un scalaire (ou moins de dimensions).
arr = np.array([0, 1, 2, 3, 4]) arr.sum() // 10 arr.mean() // 2.0 arr.std() // 1.41... arr.max() // 4 arr.min() // 0 arr.argmin() // 0 (Index de la valeur min) arr.argmax() // 4 (Index de la valeur max) // (Forme fonctionnelle np.* identique) np.sum(arr) np.mean(arr)
axis (Crucial)L'argument axis spécifie la dimension sur laquelle l'opération (agrégation) doit être **effectuée (réduite/effondrée)**.
Pour un array 2D (Lignes, Colonnes) :
axis=0: Réduit/Effondre les **Lignes** ("vers le bas", "down the rows"). Calcule une statistique *par colonne*.axis=1: Réduit/Effondre les **Colonnes** ("vers le côté", "across the columns"). Calcule une statistique *par ligne*.
Diagramme
arr = np.array([[1, 2, 3],
[4, 5, 6]])
// Shape: (2, 3)
// 1. axis=0 (Effondre les lignes)
// (Moyenne "verticale")
// ( (1+4)/2 , (2+5)/2 , (3+6)/2 )
result = arr.mean(axis=0)
// [2.5, 3.5, 4.5] (Shape: (3,))
// 2. axis=1 (Effondre les colonnes)
// (Moyenne "horizontale")
// ( (1+2+3)/3 , (4+5+6)/3 )
result = arr.mean(axis=1)
// [2., 5.] (Shape: (2,))
.reshape()
Change la forme (shape) de l'array sans changer les données (le size doit correspondre).
a = np.arange(12) // [0...11], Shape (12,) // Reshape (3 lignes, 4 cols) b = a.reshape(3, 4) // [[ 0, 1, 2, 3], // [ 4, 5, 6, 7], // [ 8, 9, 10, 11]] // (Utiliser -1 pour "auto-calculer") c = a.reshape(3, -1) // (Identique)
.T (Transpose)
Inverse les axes (lignes <-> colonnes).
b = np.array([[1, 2], [3, 4]]) // Transpose b.T // [[1, 3], // [2, 4]] // .flatten() // (Aplatit en 1D) b.flatten() // [1, 2, 3, 4]
@ & np.linalg)* (astérisque) = Multiplication Element-wise. @ (arobase) = Multiplication de Matrices (Dot Product).
@ (Matmul)
a = np.ones((2, 3)) b = np.ones((3, 2)) // (2, 3) @ (3, 2) -> (2, 2) c = a @ b // (Équivalent à np.dot(a, b))
np.linalg (Linear Algebra)
from numpy import linalg as la m = np.array([[1, 2], [3, 4]]) // Inverse la.inv(m) // Déterminant la.det(m) // Valeurs propres / Vecteurs propres la.eig(m)
Les "Ufuncs" sont des fonctions qui opèrent de manière "element-wise" (vectorisées) sur des arrays.
arr = np.array([0, np.pi/2, np.pi]) // Fonctions trigo np.sin(arr) // [0. , 1. , 1.22e-16] // Exponentielles / Log arr_exp = np.exp(arr) arr_log = np.log(arr_exp)
NaN (Not a Number)np.nan (Not a Number) est la valeur "flottante" utilisée pour les données manquantes. (NaN "infecte" les calculs).
arr = np.array([1.0, 2.0, np.nan, 4.0]) // 1. Les aggrégations standard échouent arr.mean() // nan // 2. Détection np.isnan(arr) // [False, False, True, False] arr[~np.isnan(arr)] // Filtre les NaN // 3. Agrégations "Nan-safe" (Ignoré) np.nansum(arr) // 7.0 np.nanmean(arr) // 2.33...
NumPy est la **fondation**. Quasiment toutes les bibliothèques de Data Science, ML et IA en Python dépendent de NumPy.
| Bibliothèque | Relation avec NumPy |
|---|---|
| Pandas | Construit sur NumPy. Une Series Pandas est un ndarray + un Index. |
| Scikit-learn | Prend des ndarray NumPy en entrée (X, y) pour .fit(). |
| PyTorch / TensorFlow | Les Tensors sont des ndarray "sur stéroïdes" (GPU + Autograd). Conversion .numpy() / torch.from_numpy(). |
| Matplotlib / Seaborn | Prennent des ndarray NumPy en entrée pour créer des graphiques. |
| SciPy | Construit sur NumPy. Ajoute des fonctions scientifiques (stats, optimisation, FFT). |
Ressources pour apprendre et travailler avec NumPy.
| Site | Description |
|---|---|
| numpy.org | Le site officiel. Point d'entrée pour l'installation. |
| NumPy User Guide | (numpy.org/doc/stable/user) La **RÉFÉRENCE ABSOLUE**. Explique Broadcasting, Indexing, etc. |
| API Reference | Détail de chaque fonction (ex: np.array). |
NumPy = Calcul. Pandas = Analyse.
| Critère | NumPy (ndarray) | Pandas (DataFrame) |
|---|---|---|
| Types de données | Homogène (Un seul dtype, ex: float64). | Hétérogène (Multi-dtype, ex: 'nom' (str), 'age' (int)). |
| Index | Entiers (0, 1, 2...). | Index (Labels) (ex: dates, noms, 0, 1...). |
| Usage | Calcul matriciel, Algèbre linéaire, (Input pour ML). | Charger (CSV/SQL), Nettoyer (NaN), Agréger (GroupBy), Analyser. |
| Données Manquantes | np.nan. (nansum, nanmean). | API riche (.isnull(), .dropna(), .fillna()). |
1. Création
import numpy as np a = np.array([[1, 2], [3, 4]]) z = np.zeros((2, 2)) r = np.arange(0, 10, 2)
2. Attributs
a.shape // (2, 2) a.dtype // int64 a.ndim // 2
3. Slicing
a[0, 1] // 2 a[:, 0] // [1, 3] (Col 0) a[0, :] // [1, 2] (Row 0)
4. Filtre (Mask)
mask = a > 2 a[mask] // [3, 4]
5. Ops (Vectorisation)
b = a * 2 // Element-wise c = a @ b // Matmul
6. Agrégation (axis)
// Somme totale a.sum() // Somme "verticale" (par col) a.sum(axis=0) // [4, 6] // Somme "horizontale" (par ligne) a.sum(axis=1) // [3, 7]
