NumPy
Un ndarray possède un dtype fixe décrivant chaque emplacement ; une forme (2, 3) signifie deux lignes et trois colonnes, pas deux listes Python indépendantes. Cette référence couvre les tableaux denses en mémoire et suppose l’indexation et les tranches Python. Les API utilisées existent dans NumPy 1.26 et 2.x ; précisez les types de largeur fixe si la représentation importe, car largeur entière inférée et promotions peuvent varier. Les entiers ont une plage finie et peuvent déborder.
Site officiel
Importer NumPy
import numpy as np
Création de tableaux
Créer des tableaux
# One-dimensional array
a = np.array([1, 2, 3], dtype=np.int64)
print(a)
# [1 2 3]
print(a.ndim)
# 1
# Multi-dimensional array
b = np.array([[1,2,3],[4,5,6]])
print(b)
# [[1 2 3]
# [4 5 6]]
Attributs des tableaux
# Shape of array
b.shape # (2, 3)
# Type of elements in the array
a.dtype # dtype('int64')
# Floats in numpy arrays
c = np.array([2.2, 5, 1.1])
print(c.dtype.name)
# float64
print(c)
# [2.2 5. 1.1]
Créer des tableaux avec des valeurs initiales
# Array of zeros
d = np.zeros((2,3))
print(d)
# [[0. 0. 0.]
# [0. 0. 0.]]
# Array of ones
e = np.ones((2,3))
print(e)
# [[1. 1. 1.]
# [1. 1. 1.]]
# Array with random numbers
rng = np.random.default_rng(42)
print(rng.random((2, 3)))
# [[0.77395605 0.43887844 0.85859792]
# [0.69736803 0.09417735 0.97562235]]
Créer des séquences
# Sequence of numbers
f = np.arange(10, 50, 2)
print(f)
# [10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48]
# Sequence of floats
print(np.linspace(0, 2, 15))
# [0. 0.14285714 0.28571429 0.42857143 0.57142857 0.71428571
# 0.85714286 1. 1.14285714 1.28571429 1.42857143 1.57142857
# 1.71428571 1.85714286 2. ]
Formes, axes et diffusion
La diffusion compare les dimensions depuis la droite : chaque paire doit être égale ou contenir 1 ; les dimensions initiales absentes valent 1. Ainsi (2, 3) + (3,) ajoute un vecteur à chaque ligne, tandis que (2, 3) + (2,) échoue. Transformez ce dernier en (2, 1) pour ajouter une valeur par ligne. La diffusion évite de copier les entrées répétées, mais les sorties et intermédiaires occupent de la mémoire.
L’axis d’une réduction est la dimension supprimée : axis=0 réduit les lignes et laisse une valeur par colonne ; axis=1 réduit les colonnes et laisse une valeur par ligne. keepdims=True conserve un axe de taille 1 pour une diffusion ultérieure. Le remodelage conserve le nombre d’éléments ; une seule dimension -1 peut être inférée. Un vecteur unidimensionnel n’a pas d’orientation ligne/colonne : .T ne change pas sa forme. Utilisez v[:, None] pour une colonne.
x = np.arange(6).reshape(2, 3)
assert (x + np.array([10, 20, 30])).tolist() == [[10, 21, 32], [13, 24, 35]]
assert x.sum(axis=0).tolist() == [3, 5, 7]
assert x.sum(axis=1).tolist() == [3, 12]
centered = x - x.mean(axis=1, keepdims=True)
assert centered.tolist() == [[-1.0, 0.0, 1.0], [-1.0, 0.0, 1.0]]
assert x.reshape(-1).shape == (6,)
Opérations sur les tableaux
Opérations arithmétiques
# Creating arrays
a = np.array([10,20,30,40])
b = np.array([1, 2, 3, 4])
# Elementwise operations
print(a - b)
# [ 9 18 27 36]
print(a * b)
# [ 10 40 90 160]
# Converting Fahrenheit to Celsius
fahrenheit = np.array([0, -10, -5, -15, 0])
celsius = (fahrenheit - 32) * (5/9)
print(celsius)
# [-17.77777778 -23.33333333 -20.55555556 -26.11111111 -17.77777778]
Tableaux booléens
# Boolean array example
print(celsius > -20)
# [ True False False False True]
print(celsius % 2 == 0)
# [False False False False False]
Opérations matricielles
A = np.array([[1,1],[0,1]])
B = np.array([[2,0],[3,4]])
# Elementwise product
print(A * B)
# [[2 0]
# [0 4]]
# Matrix product
print(A @ B)
# [[5 4]
# [3 4]]
Conversion ascendante de type
array1 = np.array([[1, 2, 3], [4, 5, 6]])
array2 = np.array([[7.1, 8.2, 9.1], [10.4, 11.2, 12.3]])
# Addition of arrays
array3 = array1 + array2
print(array3)
# [[ 8.1 10.2 12.1]
# [14.4 16.2 18.3]]
print(array3.dtype)
# float64
Fonctions d’agrégation
# Sum, max, min, and mean
print(array3.sum())
# 79.3
print(array3.max())
# 18.3
print(array3.min())
# 8.1
print(array3.mean())
# 13.216666666666667
# Aggregation on 2D arrays
b = np.arange(1, 16, 1).reshape(3, 5)
print(b)
# [[ 1 2 3 4 5]
# [ 6 7 8 9 10]
# [11 12 13 14 15]]
Indexation, découpage et itération
Indexation
# One-dimensional array
a = np.array([1, 3, 5, 7])
print(a[2])
# 5
# Multidimensional array
a = np.array([[1, 2], [3, 4], [5, 6]])
print(a[1, 1])
# 4
print(np.array([a[0, 0], a[1, 1], a[2, 1]]))
# [1 4 6]
print(a[[0, 1, 2], [0, 1, 1]])
# [1 4 6]
Indexation booléenne
# Boolean array example
print(a > 5)
# [[False False]
# [False False]
# [False True]]
print(a[a > 5])
# [6]
Découpage
# One-dimensional slicing
a = np.array([0, 1, 2, 3, 4, 5])
print(a[:3])
# [0 1 2]
print(a[2:4])
# [2 3]
# Multidimensional slicing
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a[:2])
# [[1 2 3 4]
# [5 6 7 8]]
print(a[:2, 1:3])
# [[2 3]
# [6 7]]
Les tranches partagent généralement la mémoire
# Basic slicing usually returns a view that shares memory with the source.
sub_array = a[:2, 1:3]
sub_array[0, 0] = 50
print(sub_array[0, 0])
# 50
print(a[0, 1])
# 50
print(np.shares_memory(a, sub_array))
# True
# Use copy() when the result must be independent.
independent = a[:2, 1:3].copy()
L’indexation avancée avec des tableaux d’entiers ou booléens renvoie généralement une copie à la place. Utilisez np.shares_memory() lorsque cette distinction importe.
Charger un petit jeu de données délimité
Un exemple autonome évite de dépendre d’un fichier téléchargé particulier ou d’un schéma de colonnes précis :
from io import StringIO
csv_data = StringIO("""height,score
1.70,82
1.82,91
1.65,76
""")
records = np.genfromtxt(csv_data, delimiter=",", names=True)
print(records.dtype.names)
# ('height', 'score')
print(records["score"].mean())
# 83.0
Copies, comparaison numérique et reproductibilité
Le contrat copie/vue est précis : les tranches de base partagent les données ; une lecture par tableau d’entiers ou de booléens crée une copie. L’affectation directe x[x < 0] = 0 modifie pourtant bien x. reshape renvoie une vue si possible, sinon une copie ; flatten() copie toujours. a + b crée normalement un résultat, tandis que a += b écrit dans a sans pouvoir changer implicitement son dtype pour accueillir des flottants. En multiplication matricielle 2-D, (m, k) @ (k, n) donne (m, n) ; * agit élément par élément.
== produit un tableau booléen, pas un verdict unique. np.array_equal vérifie valeurs exactes et forme. Pour les flottants, np.allclose teste abs(a-b) <= atol + rtol*abs(b) ; choisissez les tolérances selon les unités et la précision du problème. La diffusion étant permise, vérifiez la forme séparément si nécessaire. Les NaN restent inégaux sauf avec equal_nan=True. Les réductions comme sum propagent NaN ; nansum l’ignore, ce qui change la règle de données manquantes.
arange exclut la borne finale et les pas flottants peuvent accumuler des arrondis ; linspace fixe un nombre de points et inclut la fin par défaut. L’exemple aléatoire emploie un Generator local avec graine : le relancer reprend le même flux dans un environnement identique. Pour une reproduction exacte à long terme, notez version NumPy et générateur ; la graine seule ne garantit pas un flux identique entre versions.
expected = np.array([0.3])
actual = np.array([0.1]) + 0.2
assert not np.array_equal(actual, expected)
assert actual.shape == expected.shape
assert np.allclose(actual, expected, rtol=0, atol=1e-15)
Documentation
Explorer les liens
Cette note n’a pas encore de liens vers d’autres notes.