
# NUMPY CHEATSHEET COMPLÈTE - Guide de Référence Exhaustif



[OK] 1. IMPORT ET CONFIGURATION


import numpy as np

# Configuration de l'affichage
np.set_printoptions(precision=3, suppress=True)  # 3 décimales, pas de notation scientifique
np.set_printoptions(threshold=10)                # Limite d'éléments affichés

# Version de NumPy
print(np.__version__)



[OK] 2. CRÉATION D'ARRAYS


# --- Arrays de base ---
arr_1d = np.array([1, 2, 3, 4, 5])                    # Array 1D
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])            # Array 2D (matrice)
arr_3d = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])  # Array 3D

# --- Arrays initialisés ---
zeros = np.zeros((3, 4))                              # Matrice 3×4 de zéros
ones = np.ones((2, 3, 4))                            # Tensor 2×3×4 de uns
empty = np.empty((2, 2))                             # Array vide (non initialisé, rapide)
full = np.full((3, 3), 7)                            # Matrice 3×3 remplie de 7
eye = np.eye(4)                                      # Matrice identité 4×4
identity = np.identity(3)                            # Identité 3×3 (comme eye)
diag = np.diag([1, 2, 3, 4])                        # Matrice diagonale

# --- Séquences ---
arange = np.arange(0, 10, 2)                         # [0, 2, 4, 6, 8] - pas de 2
linspace = np.linspace(0, 1, 5)                      # 5 valeurs équidistantes entre 0 et 1
logspace = np.logspace(0, 3, 4)                      # [10^0, 10^1, 10^2, 10^3]
geomspace = np.geomspace(1, 1000, 4)                 # Progression géométrique

# --- Arrays depuis autres structures ---
from_list = np.array([1, 2, 3])                      # Depuis une liste
from_tuple = np.array((1, 2, 3))                     # Depuis un tuple
from_string = np.fromstring('1 2 3', sep=' ')        # Depuis une chaîne
from_func = np.fromfunction(lambda i, j: i + j, (3, 3))  # Fonction des indices



[OK] 3. ARRAYS ALÉATOIRES (np.random)


# --- Distribution uniforme ---
uniform = np.random.rand(3, 4)                       # Uniforme [0, 1)
uniform_range = np.random.uniform(5, 10, (3, 4))    # Uniforme [5, 10)

# --- Distribution normale (gaussienne) ---
normal = np.random.randn(3, 4)                       # Normale standard (μ=0, σ=1)
normal_custom = np.random.normal(50, 10, (3, 4))    # Normale (μ=50, σ=10)

# --- Entiers aléatoires ---
randint = np.random.randint(0, 10, size=(3, 4))     # Entiers de 0 à 9
randint_low_high = np.random.randint(5, 15, 10)     # Entiers de 5 à 14

# --- Échantillonnage ---
choice = np.random.choice([1, 2, 3, 4], size=10)    # Avec remplacement
choice_no_replace = np.random.choice(10, size=5, replace=False)  # Sans remplacement
weighted = np.random.choice([1, 2, 3], p=[0.5, 0.3, 0.2], size=10)  # Avec probabilités

# --- Mélange ---
arr = np.array([1, 2, 3, 4, 5])
np.random.shuffle(arr)                               # Mélange en place
permuted = np.random.permutation(arr)                # Retourne un mélange (ne modifie pas l'original)

# --- Seed pour reproductibilité ---
np.random.seed(42)                                   # Fixe la graine aléatoire
rng = np.random.default_rng(42)                     # Générateur moderne (recommandé)
random_arr = rng.random((3, 3))                      # Utilise le générateur



[OK] 4. PROPRIÉTÉS ET INFORMATIONS


arr = np.array([[1, 2, 3], [4, 5, 6]])

arr.shape                    # (2, 3) - dimensions
arr.ndim                     # 2 - nombre de dimensions
arr.size                     # 6 - nombre total d'éléments
arr.dtype                    # dtype('int64') - type de données
arr.itemsize                 # 8 - taille en octets d'un élément
arr.nbytes                   # 48 - taille totale en octets (size × itemsize)
arr.strides                  # (24, 8) - pas en mémoire
arr.flags                    # Informations sur le layout mémoire



[OK] 5. TYPES DE DONNÉES (dtype)


# --- Création avec type spécifique ---
int_arr = np.array([1, 2, 3], dtype=np.int32)       # Entiers 32 bits
float_arr = np.array([1, 2, 3], dtype=np.float64)   # Flottants 64 bits
bool_arr = np.array([True, False], dtype=bool)      # Booléens
complex_arr = np.array([1+2j, 3+4j], dtype=complex) # Nombres complexes

# --- Conversion de type ---
arr = np.array([1.5, 2.7, 3.9])
int_converted = arr.astype(int)                      # Convertir en int
str_arr = arr.astype(str)                            # Convertir en string

# --- Types disponibles ---
# int8, int16, int32, int64
# uint8, uint16, uint32, uint64
# float16, float32, float64
# complex64, complex128
# bool, object, string_, unicode_



[OK] 6. RESHAPE ET REDIMENSIONNEMENT


arr = np.arange(12)

# --- Reshape (créer une nouvelle forme) ---
reshaped = arr.reshape(3, 4)                         # 3 lignes × 4 colonnes
auto_reshape = arr.reshape(3, -1)                    # -1 calcule automatiquement (3×4)
three_d = arr.reshape(2, 2, 3)                       # Reshape en 3D

# --- Flatten et ravel (aplatir en 1D) ---
flat = arr.reshape(3, 4).flatten()                   # Copie aplatie
ravel = arr.reshape(3, 4).ravel()                    # Vue aplatie (si possible)

# --- Transpose ---
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
transposed = arr_2d.T                                # Transposée
transpose_axes = arr_2d.transpose()                  # Équivalent à .T
swap_axes = np.swapaxes(arr_2d, 0, 1)               # Échanger les axes

# --- Expansion de dimensions ---
arr_1d = np.array([1, 2, 3])
expanded = arr_1d[np.newaxis, :]                     # (3,) -> (1, 3)
expanded2 = arr_1d[:, np.newaxis]                    # (3,) -> (3, 1)
expand_dims = np.expand_dims(arr_1d, axis=0)        # Ajouter une dimension

# --- Squeeze (supprimer dimensions de taille 1) ---
arr = np.zeros((1, 3, 1, 4))
squeezed = arr.squeeze()                             # (1,3,1,4) -> (3,4)



[OK] 7. INDEXATION ET SLICING


arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])

# --- Indexation de base ---
element = arr[0, 2]                                  # Élément ligne 0, colonne 2 -> 3
row = arr[1]                                         # Deuxième ligne -> [5, 6, 7, 8]
col = arr[:, 2]                                      # Troisième colonne -> [3, 7, 11]

# --- Slicing ---
sub_arr = arr[0:2, 1:3]                             # Sous-matrice [[2, 3], [6, 7]]
every_other = arr[::2, ::2]                         # Une ligne/colonne sur deux
reversed = arr[::-1, ::-1]                          # Inverser lignes et colonnes

# --- Indexation avancée (fancy indexing) ---
rows = [0, 2]
cols = [1, 3]
fancy = arr[[0, 2], [1, 3]]                         # Éléments (0,1) et (2,3) -> [2, 12]
row_selection = arr[[0, 2]]                         # Lignes 0 et 2
col_selection = arr[:, [1, 3]]                      # Colonnes 1 et 3

# --- Indexation booléenne (masques) ---
mask = arr > 5                                       # Masque booléen
filtered = arr[mask]                                 # [6, 7, 8, 9, 10, 11, 12]
arr[arr > 5] = 0                                    # Modifier les éléments > 5

# --- Where ---
indices = np.where(arr > 5)                          # Retourne les indices où condition = True
values = np.where(arr > 5, arr, 0)                  # Si >5: garder, sinon: 0



[OK] 8. OPÉRATIONS MATHÉMATIQUES


arr1 = np.array([1, 2, 3, 4])
arr2 = np.array([10, 20, 30, 40])

# --- Opérations scalaires ---
add = arr1 + 10                                      # [11, 12, 13, 14]
subtract = arr1 - 5                                  # [-4, -3, -2, -1]
multiply = arr1 * 2                                  # [2, 4, 6, 8]
divide = arr1 / 2                                    # [0.5, 1.0, 1.5, 2.0]
power = arr1 ** 2                                    # [1, 4, 9, 16]
modulo = arr1 % 2                                    # [1, 0, 1, 0]
floor_div = arr1 // 2                               # [0, 1, 1, 2]

# --- Opérations élément par élément ---
add = arr1 + arr2                                    # [11, 22, 33, 44]
multiply = arr1 * arr2                               # [10, 40, 90, 160]
divide = arr2 / arr1                                 # [10.0, 10.0, 10.0, 10.0]

# --- Produits matriciels et scalaires ---
dot = np.dot(arr1, arr2)                            # Produit scalaire: 300
matrix_mult = arr1 @ arr2                           # Équivalent pour 1D: 300

mat1 = np.array([[1, 2], [3, 4]])
mat2 = np.array([[5, 6], [7, 8]])
mat_prod = mat1 @ mat2                              # Produit matriciel
mat_dot = np.dot(mat1, mat2)                        # Équivalent
matmul = np.matmul(mat1, mat2)                      # Équivalent

# --- Opérations vectorielles ---
outer = np.outer(arr1, arr2)                        # Produit extérieur (4×4)
inner = np.inner(arr1, arr2)                        # Produit intérieur
cross = np.cross([1, 2, 3], [4, 5, 6])             # Produit vectoriel



[OK] 9. FONCTIONS MATHÉMATIQUES UNIVERSELLES (ufunc)


arr = np.array([1, 4, 9, 16, 25])

# --- Racines et puissances ---
sqrt = np.sqrt(arr)                                  # Racine carrée
square = np.square(arr)                              # Carré
power = np.power(arr, 3)                            # Puissance 3
cbrt = np.cbrt(arr)                                 # Racine cubique

# --- Exponentielles et logarithmes ---
exp = np.exp(arr)                                    # e^x
exp2 = np.exp2(arr)                                  # 2^x
log = np.log(arr)                                    # Logarithme naturel (ln)
log10 = np.log10(arr)                               # Logarithme base 10
log2 = np.log2(arr)                                 # Logarithme base 2
log1p = np.log1p(arr)                               # log(1 + x) - plus précis pour petites valeurs

# --- Trigonométrie ---
angles = np.array([0, np.pi/4, np.pi/2, np.pi])
sin = np.sin(angles)                                 # Sinus
cos = np.cos(angles)                                 # Cosinus
tan = np.tan(angles)                                 # Tangente
arcsin = np.arcsin([0, 0.5, 1])                     # Arc sinus
arccos = np.arccos([0, 0.5, 1])                     # Arc cosinus
arctan = np.arctan([0, 1, np.inf])                  # Arc tangente
arctan2 = np.arctan2([1, 0], [0, 1])                # Arc tangente à 2 arguments

# --- Hyperboliques ---
sinh = np.sinh(arr)                                  # Sinus hyperbolique
cosh = np.cosh(arr)                                  # Cosinus hyperbolique
tanh = np.tanh(arr)                                  # Tangente hyperbolique

# --- Arrondissement ---
arr_float = np.array([1.2, 2.5, 3.7, 4.9])
floor = np.floor(arr_float)                          # Arrondi inférieur [1, 2, 3, 4]
ceil = np.ceil(arr_float)                            # Arrondi supérieur [2, 3, 4, 5]
round = np.round(arr_float)                          # Arrondi standard [1, 2, 4, 5]
trunc = np.trunc(arr_float)                          # Tronquer [1, 2, 3, 4]
rint = np.rint(arr_float)                            # Arrondi au plus proche

# --- Valeur absolue et signe ---
abs_val = np.abs([-1, -2, 3])                       # Valeur absolue
absolute = np.absolute([-1, -2, 3])                 # Équivalent
sign = np.sign([-5, 0, 5])                          # Signe [-1, 0, 1]

# --- Autres ---
reciprocal = np.reciprocal(arr)                     # 1/x
clip = np.clip(arr, 5, 20)                          # Limiter entre 5 et 20



[OK] 10. STATISTIQUES ET AGRÉGATIONS


arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# --- Statistiques de base ---
sum_all = arr.sum()                                  # Somme totale: 45
mean = arr.mean()                                    # Moyenne: 5.0
median = np.median(arr)                              # Médiane: 5.0
std = arr.std()                                      # Écart-type: 2.58
var = arr.var()                                      # Variance: 6.67
min_val = arr.min()                                  # Minimum: 1
max_val = arr.max()                                  # Maximum: 9

# --- Statistiques par axe ---
sum_col = arr.sum(axis=0)                            # Somme par colonne: [12, 15, 18]
mean_row = arr.mean(axis=1)                          # Moyenne par ligne: [2, 5, 8]
std_col = arr.std(axis=0)                            # Écart-type par colonne

# --- Indices des extrema ---
argmin = arr.argmin()                                # Index du minimum (aplati): 0
argmax = arr.argmax()                                # Index du maximum (aplati): 8
argmin_axis = arr.argmin(axis=1)                    # Index min par ligne: [0, 0, 0]

# --- Percentiles et quantiles ---
percentile_50 = np.percentile(arr, 50)              # 50e percentile (médiane)
quantile_25 = np.quantile(arr, 0.25)                # 1er quartile
quantile_75 = np.quantile(arr, 0.75)                # 3e quartile

# --- Sommes cumulées et produits ---
cumsum = arr.cumsum()                                # Somme cumulée
cumsum_axis = arr.cumsum(axis=0)                    # Somme cumulée par colonne
cumprod = arr.cumprod()                              # Produit cumulé

# --- Corrélation et covariance ---
arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([2, 4, 5, 4, 5])
corrcoef = np.corrcoef(arr1, arr2)                  # Coefficient de corrélation
cov = np.cov(arr1, arr2)                            # Matrice de covariance

# --- Histogramme ---
data = np.random.randn(1000)
hist, bins = np.histogram(data, bins=10)            # Histogramme



[OK] 11. OPÉRATIONS SUR LES AXES


arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# axis=0 : opération sur les lignes (résultat par colonne)
# axis=1 : opération sur les colonnes (résultat par ligne)
# axis=None : opération sur tout l'array (défaut)

sum_axis0 = arr.sum(axis=0)                          # [12, 15, 18] - somme verticale
sum_axis1 = arr.sum(axis=1)                          # [6, 15, 24] - somme horizontale
mean_axis0 = arr.mean(axis=0)                        # [4, 5, 6]
std_axis1 = arr.std(axis=1)                          # [0.816, 0.816, 0.816]

# --- Garder les dimensions ---
sum_keepdims = arr.sum(axis=0, keepdims=True)       # Shape (1, 3) au lieu de (3,)



[OK] 12. BROADCASTING


# Broadcasting: étendre automatiquement les dimensions pour opérations

# Exemple 1: Scalaire avec array
arr = np.array([1, 2, 3])
result = arr + 10                                    # [11, 12, 13]

# Exemple 2: 1D avec 2D
arr_2d = np.array([[1, 2, 3], [4, 5, 6]])
arr_1d = np.array([10, 20, 30])
result = arr_2d + arr_1d                            # Ajoute [10,20,30] à chaque ligne

# Exemple 3: Colonne avec ligne
col = np.array([[1], [2], [3]])                     # Shape (3, 1)
row = np.array([10, 20, 30])                        # Shape (3,)
result = col + row                                   # Shape (3, 3)

# Règles du broadcasting:
# 1. Si les arrays n'ont pas le même rang, ajouter des 1 devant la shape la plus courte
# 2. Les arrays sont compatibles si pour chaque dimension, les tailles sont égales ou l'une vaut 1
# 3. Après broadcasting, chaque array se comporte comme s'il avait la shape maximale



[OK] 13. CONCATENATION, STACKING ET SPLITTING


arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])

# --- Concatenation ---
concat_rows = np.concatenate([arr1, arr2], axis=0)  # Concaténer verticalement (4×2)
concat_cols = np.concatenate([arr1, arr2], axis=1)  # Concaténer horizontalement (2×4)

# --- Stacking ---
vstack = np.vstack([arr1, arr2])                    # Empiler verticalement (identique concat axis=0)
hstack = np.hstack([arr1, arr2])                    # Empiler horizontalement
dstack = np.dstack([arr1, arr2])                    # Empiler en profondeur (2×2×2)

# --- Column et row stack ---
col_stack = np.column_stack([arr1, arr2])           # Concaténer comme colonnes
row_stack = np.row_stack([arr1, arr2])              # Concaténer comme lignes

# --- Splitting ---
arr = np.arange(12).reshape(4, 3)
split_h = np.split(arr, 2, axis=0)                  # Diviser en 2 parties horizontalement
split_v = np.split(arr, 3, axis=1)                  # Diviser en 3 parties verticalement
hsplit = np.hsplit(arr, 3)                          # Split horizontal (par colonnes)
vsplit = np.vsplit(arr, 2)                          # Split vertical (par lignes)

# --- Repeat et tile ---
arr = np.array([1, 2, 3])
repeated = np.repeat(arr, 3)                        # [1,1,1,2,2,2,3,3,3]
tiled = np.tile(arr, 3)                             # [1,2,3,1,2,3,1,2,3]
tiled_2d = np.tile(arr, (2, 2))                     # Répéter en 2D



[OK] 14. CONDITIONS ET LOGIQUE


arr = np.array([1, 2, 3, 4, 5, 6])

# --- Where (condition ternaire) ---
result = np.where(arr > 3, 100, 0)                  # Si >3: 100, sinon: 0
result2 = np.where(arr > 3, arr * 10, arr)          # Si >3: x10, sinon: inchangé

# --- Select (conditions multiples) ---
conditions = [arr < 3, arr == 3, arr > 3]
choices = [1, 2, 3]
result = np.select(conditions, choices, default=0)  # 1 si <3, 2 si =3, 3 si >3

# --- Comparaisons ---
equal = arr == 3                                     # [False, False, True, False, False, False]
not_equal = arr != 3
greater = arr > 3
less_equal = arr <= 3

# --- Comparaisons entre arrays ---
arr2 = np.array([1, 2, 2, 5, 5, 7])
equal_arrays = np.array_equal(arr, arr2)            # False
close = np.allclose(arr, arr2, atol=1)              # True (tolérance absolue 1)

# --- Opérations logiques ---
mask1 = arr > 2
mask2 = arr < 5
logical_and = np.logical_and(mask1, mask2)          # ET logique
logical_or = np.logical_or(mask1, mask2)            # OU logique
logical_not = np.logical_not(mask1)                 # NON logique
logical_xor = np.logical_xor(mask1, mask2)          # XOR logique

# --- Any et All ---
any_true = np.any(arr > 5)                          # True si au moins un élément > 5
all_true = np.all(arr > 0)                          # True si tous les éléments > 0
any_axis = np.any(arr.reshape(2,3) > 3, axis=0)    # Par colonne



[OK] 15. TRI ET RECHERCHE


arr = np.array([3, 1, 4, 1, 5, 9, 2, 6])

# --- Tri ---
sorted_arr = np.sort(arr)                           # Retourne une copie triée
arr.sort()                                          # Trie en place

# --- Tri par axe ---
arr_2d = np.array([[3, 1, 4], [1, 5, 9]])
sorted_cols = np.sort(arr_2d, axis=0)               # Trier chaque colonne
sorted_rows = np.sort(arr_2d, axis=1)               # Trier chaque ligne

# --- Argsort (indices triés) ---
indices = np.argsort(arr)                           # Indices qui trieraient l'array
sorted_by_index = arr[indices]                      # Utiliser les indices

# --- Partition ---
partitioned = np.partition(arr, 3)                  # 3 plus petits éléments d'abord (non triés)
argpartition = np.argpartition(arr, 3)              # Indices de partition

# --- Recherche ---
arr_sorted = np.array([1, 2, 3, 4, 5, 6, 7, 8])
index = np.searchsorted(arr_sorted, 5)              # Index où insérer 5 (recherche binaire)
indices = np.searchsorted(arr_sorted, [2, 4, 6])   # Plusieurs valeurs

# --- Éléments uniques ---
arr = np.array([1, 2, 2, 3, 3, 3, 4])
unique = np.unique(arr)                             # [1, 2, 3, 4]
unique, counts = np.unique(arr, return_counts=True) # Avec comptages
unique, indices = np.unique(arr, return_index=True) # Avec premiers indices

# --- Extraire éléments ---
nonzero = np.nonzero(arr)                           # Indices des éléments non-zéros
flatnonzero = np.flatnonzero(arr)                   # Version aplatie



[OK] 16. ALGÈBRE LINÉAIRE (np.linalg)


# --- Opérations matricielles ---
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])

inverse = np.linalg.inv(A)                          # Inverse de matrice
det = np.linalg.det(A)                              # Déterminant
trace = np.trace(A)                                  # Trace (somme diagonale)
rank = np.linalg.matrix_rank(A)                     # Rang de la matrice

# --- Résolution de systèmes linéaires ---
# Résoudre Ax = b
A = np.array([[3, 1], [1, 2]])
b = np.array([9, 8])
x = np.linalg.solve(A, b)                           # Solution: x = [2, 3]

# --- Valeurs et vecteurs propres ---
eigenvalues, eigenvectors = np.linalg.eig(A)        # Valeurs propres et vecteurs propres
eigenvalues = np.linalg.eigvals(A)                  # Seulement valeurs propres

# --- Décompositions ---
# SVD (Singular Value Decomposition)
U, s, Vt = np.linalg.svd(A)                         # A = U @ diag(s) @ Vt

# QR Decomposition
Q, R = np.linalg.qr(A)                              # A = Q @ R

# Cholesky (pour matrices symétriques définies positives)
A_sym = np.array([[4, 2], [2, 3]])
L = np.linalg.cholesky(A_sym)                       # A = L @ L.T

# --- Normes ---
vector_norm = np.linalg.norm([3, 4])                # Norme L2 (euclidienne): 5.0
matrix_norm = np.linalg.norm(A)                     # Norme de Frobenius
inf_norm = np.linalg.norm(A, np.inf)                # Norme infinie
l1_norm = np.linalg.norm(A, 1)                      # Norme L1

# --- Puissance matricielle ---
mat_power = np.linalg.matrix_power(A, 3)            # A^3

# --- Produit tensoriel ---
tensor_prod = np.kron(A, B)                         # Produit de Kronecker



[OK] 17. MANIPULATION DE DONNÉES


arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# --- Insertion et suppression ---
inserted = np.insert(arr, 1, [10, 11, 12], axis=0) # Insérer ligne à l'index 1
deleted = np.delete(arr, 1, axis=0)                # Supprimer ligne à l'index 1
appended = np.append(arr, [[10, 11, 12]], axis=0)  # Ajouter une ligne

# --- Remplacement ---
arr_copy = arr.copy()
np.put(arr_copy, [0, 4, 8], [99, 99, 99])          # Remplacer indices spécifiques
np.place(arr_copy, arr_copy > 5, 0)                 # Remplacer où condition vraie

# --- Extraction diagonale ---
diag = np.diag(arr)                                  # Diagonale principale [1, 5, 9]
diag_offset = np.diagonal(arr, offset=1)            # Diagonale supérieure [2, 6]

# --- Remplir ---
arr_filled = np.full_like(arr, 5)                   # Même forme, rempli de 5
zeros_like = np.zeros_like(arr)                     # Même forme, rempli de 0
ones_like = np.ones_like(arr)                       # Même forme, rempli de 1



[OK] 18. COPIE ET VUES


arr = np.array([1, 2, 3, 4, 5])

# --- Vue (view) - partage la mémoire ---
view = arr.view()                                    # Vue de l'array
view[0] = 100                                        # Modifie aussi arr!

slice_view = arr[1:4]                               # Le slicing crée une vue
slice_view[0] = 200                                 # Modifie arr[1]!

# --- Copie profonde (copy) - données indépendantes ---
copy = arr.copy()                                    # Copie indépendante
copy[0] = 300                                        # N'affecte pas arr

# --- Vérifier si c'est une copie ou une vue ---
is_view = copy.base is arr                          # False pour copie
is_view = view.base is arr                          # True pour vue



[OK] 19. ENTRÉES/SORTIES (I/O)


arr = np.array([[1, 2, 3], [4, 5, 6]])

# --- Sauvegarder et charger (format binaire .npy) ---
np.save('array.npy', arr)                           # Sauvegarder un array
loaded = np.load('array.npy')                       # Charger un array

# --- Sauvegarder plusieurs arrays (.npz) ---
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
np.savez('arrays.npz', a=arr1, b=arr2)             # Sauvegarder plusieurs
data = np.load('arrays.npz')                        # Charger
arr1_loaded = data['a']
arr2_loaded = data['b']

# --- Fichiers texte ---
np.savetxt('array.txt', arr, delimiter=',')        # Sauvegarder en CSV
loaded_txt = np.loadtxt('array.txt', delimiter=',') # Charger depuis CSV

# --- Fichiers texte avec en-têtes ---
np.savetxt('data.csv', arr, delimiter=',', 
           header='col1,col2,col3', comments='')    # Avec en-tête

# --- Depuis/vers bytes ---
bytes_data = arr.tobytes()                          # Convertir en bytes
from_bytes = np.frombuffer(bytes_data, dtype=int)  # Depuis bytes

# --- Depuis/vers liste Python ---
list_data = arr.tolist()                            # Convertir en liste Python
from_list = np.array(list_data)                     # Depuis liste



[OK] 20. NOMBRES COMPLEXES


complex_arr = np.array([1+2j, 3+4j, 5+6j])

real_part = complex_arr.real                        # Partie réelle [1, 3, 5]
imag_part = complex_arr.imag                        # Partie imaginaire [2, 4, 6]
conjugate = np.conj(complex_arr)                    # Conjugué [1-2j, 3-4j, 5-6j]
absolute = np.abs(complex_arr)                      # Module |z|
angle = np.angle(complex_arr)                       # Argument (angle)



[OK] 21. POLYNÔMES


# Polynôme: p(x) = 3x² + 2x + 1
coeffs = [3, 2, 1]                                  # Coefficients (degré décroissant)

# --- Évaluation ---
result = np.polyval(coeffs, 5)                      # p(5) = 3*25 + 2*5 + 1 = 86
results = np.polyval(coeffs, [1, 2, 3])            # Évaluer pour plusieurs x

# --- Racines ---
roots = np.roots(coeffs)                            # Trouver les racines

# --- Opérations sur polynômes ---
p1 = [1, 2, 3]                                      # x² + 2x + 3
p2 = [1, 1]                                         # x + 1
add = np.polyadd(p1, p2)                           # Addition
sub = np.polysub(p1, p2)                           # Soustraction
mul = np.polymul(p1, p2)                           # Multiplication
div, remainder = np.polydiv(p1, p2)                # Division

# --- Dérivée et intégrale ---
derivative = np.polyder(coeffs)                     # Dérivée
integral = np.polyint(coeffs)                       # Intégrale

# --- Fit polynomial ---
x = np.array([0, 1, 2, 3, 4])
y = np.array([1, 3, 7, 13, 21])
coeffs_fit = np.polyfit(x, y, 2)                   # Fit polynôme degré 2


[OK] 22. ENSEMBLES (OPÉRATIONS SET)


arr1 = np.array([1, 2, 3, 4, 5])
arr2 = np.array([3, 4, 5, 6, 7])

# --- Opérations d'ensemble ---
union = np.union1d(arr1, arr2)                      # Union [1,2,3,4,5,6,7]
intersection = np.intersect1d(arr1, arr2)           # Intersection [3,4,5]
difference = np.setdiff1d(arr1, arr2)               # Différence [1,2]
symmetric_diff = np.setxor1d(arr1, arr2)            # Différence symétrique [1,2,6,7]

# --- Appartenance ---
is_in = np.in1d(arr1, arr2)                         # [False,False,True,True,True]
contains = np.isin([1, 5, 9], arr1)                 # [True,True,False]



[OK] 23. FONCTIONS FINANCIÈRES


# --- Valeur future ---
fv = np.fv(0.05/12, 10*12, -100, -1000)            # Valeur future (taux, périodes, pmt, pv)

# --- Valeur présente ---
pv = np.pv(0.05/12, 10*12, -100)                   # Valeur présente

# --- Paiement ---
pmt = np.pmt(0.05/12, 10*12, 15000)                # Paiement mensuel

# --- Taux d'intérêt ---
rate = np.rate(10*12, -100, 1000, 0)               # Taux d'intérêt

# --- Nombre de périodes ---
nper = np.nper(0.05/12, -100, 1000)                # Nombre de périodes

# --- TRI (Taux de rendement interne) ---
cashflows = [-1000, 300, 400, 500, 600]
irr = np.irr(cashflows)                             # Taux de rendement interne

# --- VAN (Valeur actualisée nette) ---
npv = np.npv(0.1, cashflows)                        # VAN avec taux 10%



[OK] 24. STRUCTURED ARRAYS (ARRAYS STRUCTURÉS)


# Créer un dtype structuré
dtype = [('name', 'U10'), ('age', 'i4'), ('weight', 'f4')]
data = np.array([('Alice', 25, 55.5), 
                 ('Bob', 30, 75.2),
                 ('Charlie', 35, 80.0)], dtype=dtype)

# Accès par champ
names = data['name']                                # ['Alice', 'Bob', 'Charlie']
ages = data['age']                                  # [25, 30, 35]

# Accès par enregistrement
first_person = data[0]                              # ('Alice', 25, 55.5)

# Tri par champ
sorted_data = np.sort(data, order='age')           # Trier par âge



[OK] 25. MASQUES ET ARRAYS MASQUÉS (np.ma)


# Créer un masked array (pour données manquantes)
data = np.array([1, 2, -999, 4, 5, -999])
masked = np.ma.masked_equal(data, -999)            # Masquer les -999

# Opérations ignorent les valeurs masquées
mean = masked.mean()                                # 3.0 (ignore -999)

# Créer avec masque explicite
mask = [False, False, True, False, False, True]
masked2 = np.ma.array(data, mask=mask)

# Remplir les valeurs masquées
filled = masked.filled(0)                           # Remplace -999 par 0



[OK] 26. FONCTIONS DE FENÊTRAGE (WINDOW FUNCTIONS)


# Pour traitement du signal
window_hann = np.hanning(10)                        # Fenêtre de Hann
window_hamming = np.hamming(10)                     # Fenêtre de Hamming
window_bartlett = np.bartlett(10)                   # Fenêtre de Bartlett
window_blackman = np.blackman(10)                   # Fenêtre de Blackman
window_kaiser = np.kaiser(10, 5)                    # Fenêtre de Kaiser



[OK] 27. GRADIENT ET DIFFÉRENCES


arr = np.array([1, 4, 9, 16, 25])

# --- Gradient (dérivée numérique) ---
gradient = np.gradient(arr)                         # [3, 3.5, 5.5, 7.5, 9]

# --- Différences ---
diff = np.diff(arr)                                 # [3, 5, 7, 9] - différences entre éléments
diff_n = np.diff(arr, n=2)                         # Différence d'ordre 2

# --- Différences finies ---
arr_2d = np.array([[1, 2, 4], [5, 8, 10]])
ediff = np.ediff1d(arr_2d)                         # Différences (aplati)



[OK] 28. INTERPOLATION


# Interpolation linéaire
xp = np.array([1, 2, 3, 4, 5])
fp = np.array([10, 20, 30, 40, 50])
x = np.array([1.5, 2.5, 3.5])
interpolated = np.interp(x, xp, fp)                 # [15, 25, 35]



[OK] 29. BIT OPERATIONS


a = np.array([2, 5, 8], dtype=np.uint8)
b = np.array([3, 6, 9], dtype=np.uint8)

bitwise_and = np.bitwise_and(a, b)                  # ET bit à bit
bitwise_or = np.bitwise_or(a, b)                    # OU bit à bit
bitwise_xor = np.bitwise_xor(a, b)                  # XOR bit à bit
bitwise_not = np.bitwise_not(a)                     # NOT bit à bit (inversion)
left_shift = np.left_shift(a, 2)                    # Décalage gauche (× 4)
right_shift = np.right_shift(a, 1)                  # Décalage droite (÷ 2)



[OK] 30. FONCTIONS AVANCÉES


# --- Apply along axis ---
arr = np.array([[1, 2, 3], [4, 5, 6]])
def normalize(x):
    return x / x.sum()
normalized = np.apply_along_axis(normalize, 1, arr) # Appliquer sur chaque ligne

# --- Vectorize (transformer fonction en ufunc) ---
def my_func(x, y):
    return x ** 2 + y ** 2
vectorized = np.vectorize(my_func)
result = vectorized([1, 2, 3], [4, 5, 6])          # Applique élément par élément

# --- Meshgrid (créer grilles de coordonnées) ---
x = np.array([1, 2, 3])
y = np.array([4, 5])
X, Y = np.meshgrid(x, y)                           # Grilles 2D pour coordonnées

# --- Indices avancés ---
indices = np.indices((3, 3))                        # Grilles d'indices



[OK] 31. PERFORMANCE ET OPTIMISATION


# --- Calcul en place (économie mémoire) ---
arr = np.array([1, 2, 3, 4, 5])
np.add(arr, 10, out=arr)                           # Addition en place

# --- Arrays C-contiguous vs F-contiguous ---
arr_c = np.array([[1, 2], [3, 4]], order='C')      # Row-major (C style)
arr_f = np.array([[1, 2], [3, 4]], order='F')      # Column-major (Fortran)
is_c = arr_c.flags['C_CONTIGUOUS']                  # True
is_f = arr_f.flags['F_CONTIGUOUS']                  # True

# --- Ascontiguousarray ---
contiguous = np.ascontiguousarray(arr)              # S'assurer que c'est contiguous

# --- Memory layout ---
arr.strides                                         # Pas en mémoire



[OK] 32. COMPARAISONS DE PERFORMANCES


# NumPy est bien plus rapide que les boucles Python pures
import time

# [X] Lent - Boucle Python
def sum_python(n):
    result = 0
    for i in range(n):
        result += i
    return result

# [OK] Rapide - NumPy vectorisé
def sum_numpy(n):
    return np.arange(n).sum()

# NumPy est typiquement 10-100x plus rapide!



[OK] 33. CONSEILS ET BONNES PRATIQUES


"""
[OK] À FAIRE:
- Utiliser des opérations vectorisées plutôt que des boucles
- Pré-allouer les arrays quand possible
- Utiliser des vues plutôt que des copies quand possible
- Profiler le code avec %timeit (Jupyter) ou timeit
- Utiliser dtype approprié (int32 vs int64, float32 vs float64)
- Utiliser axis parameter pour opérations sur dimensions spécifiques

[X] À ÉVITER:
- Boucles Python sur arrays NumPy
- Copier des arrays inutilement
- Créer de nouveaux arrays dans une boucle
- Utiliser append() dans une boucle (très lent)
- Ignorer les warnings de dtype
"""



[OK] 34. EXEMPLES PRATIQUES


# --- Normalisation min-max ---
def normalize_minmax(arr):
    return (arr - arr.min()) / (arr.max() - arr.min())

# --- Standardisation (z-score) ---
def standardize(arr):
    return (arr - arr.mean()) / arr.std()

# --- Distance euclidienne ---
def euclidean_distance(p1, p2):
    return np.sqrt(np.sum((p1 - p2) ** 2))

# --- Matrice de distances ---
def distance_matrix(points):
    """Calculer matrice de distances entre tous les points"""
    n = len(points)
    distances = np.zeros((n, n))
    for i in range(n):
        distances[i] = np.sqrt(np.sum((points - points[i])**2, axis=1))
    return distances

# --- Moving average (moyenne mobile) ---
def moving_average(arr, window_size):
    return np.convolve(arr, np.ones(window_size)/window_size, mode='valid')

# --- One-hot encoding ---
def one_hot_encode(arr, num_classes):
    return np.eye(num_classes)[arr]

# --- Softmax ---
def softmax(x):
    exp_x = np.exp(x - np.max(x))  # Stabilité numérique
    return exp_x / exp_x.sum()

# --- Matrice de confusion ---
def confusion_matrix(y_true, y_pred, num_classes):
    matrix = np.zeros((num_classes, num_classes), dtype=int)
    for true, pred in zip(y_true, y_pred):
        matrix[true, pred] += 1
    return matrix



[OK] 35. RESSOURCES ET DOCUMENTATION


"""
[DOCS] Documentation officielle: https://numpy.org/doc/
[RECHERCHE] Recherche de fonctions: np.lookfor('keyword')
[?] Aide sur une fonction: help(np.function_name) ou np.function_name?
[GRAPHIQUE] Tutoriels: https://numpy.org/numpy-tutorials/

Fonctions utiles pour découvrir NumPy:
- np.info(np.fonction)     : Documentation détaillée
- np.source(np.fonction)   : Code source
- dir(np)                  : Liste toutes les fonctions disponibles
"""



# FIN DE LA CHEATSHEET NUMPY
