1. Expression régulière
Les expressions régulières (ou "regex") sont des chaînes de caractères utilisées pour rechercher, extraire, ou valider des motifs (patterns) dans du texte (ex. : email, numéro de téléphone, mot-clé...).
Python fournit le module re pour les manipuler (import re)
import re
- Syntaxe des motifs (patterns)
| Motif | Signification | Exemple(s) d’utilisation |
|---|---|---|
. |
N’importe quel caractère sauf retour à la ligne | a.c : correspond à abc, axc mais pas ac |
^ |
Début de ligne | ^Hello : correspond à Hello world si la ligne commence par Hello |
$ |
Fin de ligne | end$ : correspond à the end |
[] |
Classe de caractères (ensemble autorisé) | [0-9] : un chiffre, [aeiou] : une voyelle |
\| |
OU logique (alternatives possibles) | chat\|chien : correspond à chat ou chien |
- Motifs de base
| Pattern | Signification | Exemple |
|---|---|---|
. |
N'importe quel caractère (sauf retour ligne) | a.c correspond à "abc", "a7c" |
\d |
Un chiffre (0-9) | \d\d correspond à "42" |
\D |
Tout sauf un chiffre | \D+ correspond à "abc" |
\w |
Un caractère alphanumérique ou _ |
\w+ → "Nom123" |
\W |
Tout sauf un caractère alphanumérique | \W+ → "@#!" |
\s |
Un espace, tabulation ou retour ligne | \s+ → " " |
\S |
Tout sauf un espace | \S+ → "Texte" |
- Quantificateurs:
| Pattern | Signification | Exemple |
|---|---|---|
* |
0 ou plusieurs | ab* : "a", "abbb" |
+ |
1 ou plusieurs | ab+ : "ab", "abbbb" |
? |
0 ou 1 fois | ab? : "a", "ab" |
{n} |
exactement n fois | \d{4} : "2025" |
{n,} |
au moins n fois | \d{2,} : "1234" |
{n,m} |
entre n et m fois | \d{2,4} : "123", "2025" |
- Délimiteurs et classes de caractères
| Pattern | Signification | Exemple |
|---|---|---|
[...] |
Une des valeurs listées | [abc] → "a", "b" ou "c" |
[^...] |
Tout sauf les valeurs listées | [^abc] → "d", "z" |
[0-9] |
Chiffre de 0 à 9 | [0-9]+ → "2025" |
[a-zA-Z] |
Lettre majuscule ou minuscule | [a-zA-Z]+ → "Python" |
- Début et fin de chaîne
| Pattern | Signification | Exemple |
|---|---|---|
^ |
Début de chaîne | ^Bonjour → correspond à "Bonjour Alice" |
$ |
Fin de chaîne | 2025$ → correspond à "année 2025" |
\b |
Limite de mot | \bmot\b → correspond à "mot" mais pas "motif" |
- Exemples de motifs utiles
| Objectif | Regex |
|---|---|
| Nombre entier | ^\d+$ |
| Date (format jj/mm/aaaa) | \d{2}/\d{2}/\d{4} |
- Fonctions principales de re
| Fonction | Rôle |
|---|---|
re.search() |
Recherche un motif une seule fois dans une chaîne |
re.match() |
Teste si le début de la chaîne correspond au motif |
re.findall() |
Retourne toutes les correspondances |
re.finditer() |
Idem que findall mais retourne un itérateur d'objets Match |
re.sub() |
Remplace des parties de texte selon un motif |
re.split() |
Coupe une chaîne selon un motif |
Exemples
- search()
# re.search() : Recherche un motif une seule fois dans une chaîne
import re
# Exemple 1 : présence d'un mot
texte = "Bienvenue au cours Python"
corresp = re.search(r"Python", texte)
print(corresp.group())
# Exemple 2 : chiffre dans une phrase
corresp = re.search(r"\d+", "Il a 13 ans 15 ans")
print(corresp.group()) # 13
# Exemple 3 : Non chiffre dans une phrase
corresp = re.search(r"\D+", "Il a 13 ans")
print(corresp.group())
Python 13 Il a
- match()
import re
# re.match() : Vérifie si le début de la chaîne correspond au motif.
# Exemple 1 : bon début
resultat = re.match(r"Bonjour", "Bonjour tout le monde")
print(resultat, "de type ", type(resultat))
print(resultat.group()) # .group() sert à récupérer le texte exact trouvé par la correspondance (match) : Bonjour
# Exemple 2 : ne matche pas car ce n’est pas au début
print(re.match(r"tout", "Bonjour tout le monde")) # None
<re.Match object; span=(0, 7), match='Bonjour'> de type <class 're.Match'> Bonjour None
- findall()
# re.findall() : Retourne toutes les correspondances sous forme de liste.
# Exemple 1 : trouver tous les chiffres
nums = re.findall(r"\d+", "Année 2020, puis 2024, et maintenant 2025")
print(nums) # ['2020', '2024', '2025']
# Exemple 2 : mots commençant par une majuscule
mots = re.findall(r"\b[A-Z]\w+", "Alice est avec C Bob et Oscar")
print(mots) # ['Alice', 'Bob', 'Oscar']
['2020', '2024', '2025'] ['Alice', 'Bob', 'Oscar']
- re.finditer()
# re.finditer() : Comme findall, mais retourne des objets Match, donc plus d’info
# Exemple 1 : trouver les positions des chiffres
for m in re.finditer(r"\d+", "123 et 456"):
print(f"Nombre : {m.group()}, position : {m.start()}")
# Nombre : 123, position : 0
# Nombre : 456, position : 7
# Exemple 2 : toutes les majuscules avec leur position
texte = "Python Et C"
for match in re.finditer(r"[A-Z]", texte):
print(match.group(), match.start())
# P 0
# E 7
# C 10
Nombre : 123, position : 0 Nombre : 456, position : 7 P 0 E 7 C 10
- split()
# re.split()
# Exemple 1 : couper par espace ou virgule
print(re.split(r"[ ,]+", "Python, PHP Java,, C++"))
# ['Python', 'PHP', 'Java', 'C++']
# Exemple 2 : couper à chaque chiffre
print(re.split(r"\d+", "abc123def456ghi")) # ['abc', 'def', 'ghi']
['Python', 'PHP', 'Java', 'C++'] ['abc', 'def', 'ghi']
- sub()
# re.sub(): Remplace les correspondances par une nouvelle valeur.
# Exemple 1 : anonymiser un email
texte = "Mon email est alice@gmail.com"
print(re.sub(r"\S+@\S+", "[EMAIL]", texte)) # Mon email est [EMAIL]
# Exemple 2 : remplacer tous les chiffres par '*'
print(re.sub(r"\d", "*", "Code 12345")) # Code *****
Mon email est [EMAIL] Code *****
- fullmatch()
La fonction re.fullmatch() vérifie si toute la chaîne correspond exactement au motif.
import re
motif = r"\d+" # Un ou plusieurs chiffres
print(re.fullmatch(motif, "12345")) # OK → Match
print(re.fullmatch(motif, "123abc")) # NON → None
<re.Match object; span=(0, 5), match='12345'> None
- Méthodes importantes
- ravel() : pour applatir un tableau (qu'il ne fasse plus qu'une dimension)
- squeeze() : quand une dimension est égale a 1, cette dimension disparait
- concatenate() : assemble 2 tableaux ensemble selon un axes (existe aussi en hstack et vstack)
import numpy as np
A = np.zeros((2, 3)) # création d'un tableau de shape (2, 3)
print("-------------- A")
print(A)
-------------- A [[0. 0. 0.] [0. 0. 0.]]
print("-------------- A.reshape()")
A = A.reshape((3, 2)) # redimensionne le tableau A (3 lignes, 2 colonnes)
print(A)
-------------- A.reshape() [[0. 0.] [0. 0.] [0. 0.]]
print("-------------- A.ravel()")
X = A.ravel() # Aplatit le tableau A (une seule dimension)
print(X)
-------------- A.ravel() [0. 0. 0. 0. 0. 0.]
Y = np.array([[[1, 1, 1], [2, 4, 8]]])
print ("- Y : \n", Y)
d1 = 0
print (f"\n- Y[{d1}] :\n {Y[d1]}")
d2 = 1
print (f"\n- Y[{d1},{d2}] :\n {Y[d1,d2]}")
d3 = 2
print (f"\n- Y[{d1},{d2},{d3}] :\n {Y[d1,d2,d3]}")
print("\nShape de Y : ", Y.shape)
- Y : [[[1 1 1] [2 4 8]]] - Y[0] : [[1 1 1] [2 4 8]] - Y[0,1] : [2 4 8] - Y[0,1,2] : 8 Shape de Y : (1, 2, 3)
print("-------------- squeeze() [Fr : presser]")
YP = np.squeeze(Y) # élimine les dimensions "1" de Y.
print ("Apres squeezed() Y :\n ", YP)
print("\nShape Y : ", YP.shape)
-------------- squeeze() [Fr : presser] Apres squeezed() Y : [[1 1 1] [2 4 8]] Shape Y : (2, 3)
print("-------------- squeeze() [Fr : presser]")
YP = np.squeeze(YP) # élimine les dimensions "1" de Y.
print ("Apres squeezed() Y :\n ", YP)
print("\nShape Y : ", YP.shape)
-------------- squeeze() [Fr : presser] Apres squeezed() Y : [[1 1 1] [2 4 8]] Shape Y : (2, 3)
A = np.zeros((2, 3)) # création d'un tableau de shape (2, 3)
B = np.ones((3, 3)) # création d'un tableau de shape (2, 3)
print("A :\n", A)
print("\nB :\n", B)
A : [[0. 0. 0.] [0. 0. 0.]] B : [[1. 1. 1.] [1. 1. 1.] [1. 1. 1.]]
np.concatenate((A, B), axis=0) # axe 0 : équivalent de np.vstack((A, B))
array([[0., 0., 0.],
[0., 0., 0.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])A = np.zeros((2, 3)) # création d'un tableau de shape (2, 3)
B = np.ones((2, 4)) # création d'un tableau de shape (2, 3)
print("A :\n", A)
print("\nB :\n", B)
A : [[0. 0. 0.] [0. 0. 0.]] B : [[1. 1. 1. 1.] [1. 1. 1. 1.]]
np.concatenate((A, B), axis=1) # axe 1 : équivalent de np.hstack((A, B))
array([[0., 0., 0., 1., 1., 1., 1.],
[0., 0., 0., 1., 1., 1., 1.]])Indexing et Slicing
Le fonctionnement est le meme que pour les listes
import numpy as np
A = np.array([[1, 2, 3], [4, 5, 6]])
print(A)
[[1 2 3] [4 5 6]]
# Pour selectionner les blocs de la ligne (0-1) colonne (0-1)
A[0:2, 0:2]
array([[1, 2],
[4, 5]])A[0:2, 1:] = 11
print(A)
[[ 1 11 11] [ 4 11 11]]
Boolean Indexing
A = np.array([[7, 2, 3], [4, 5, 6]])
print(A)
[[7 2 3] [4 5 6]]
print(A<5) # masque booléen
[[False True True] [ True False False]]
print(A[A < 5]) # sous-ensemble filtré par le masque booléen
[2 3 4]
A[A<5] = 412 # convertit les valeurs sélectionnées.
print(A)
[[ 7 412 412] [412 5 6]]
Fonctionnalités Mathématiques:
import numpy as np
- Méthodes de bases (les plus utiles) de la classe ndarray
A = np.array([[1, 2, 3], [4, 5, 6]])
print("------------- A:")
print(A)
print("\nsum :", A.sum()) # effectue la somme de tous les éléments du tableau
print("sum(axis=0) :", A.sum(axis=0)) # effectue la somme des colonnes (somme sur éléments des les lignes)
print("sum(axis=1) :",A.sum(axis=1)) # effectue la somme des lignes (somme sur les éléments des colonnes)
print("A.cumsum(axis=1) :\n", A.cumsum(axis=1)) # effectue la somme cumulée
print("A.cumsum(axis=0) :\n", A.cumsum(axis=0)) # effectue la somme cumulée
------------- A: [[1 2 3] [4 5 6]] sum : 21 sum(axis=0) : [5 7 9] sum(axis=1) : [ 6 15] A.cumsum(axis=1) : [[ 1 3 6] [ 4 9 15]] A.cumsum(axis=0) : [[1 2 3] [5 7 9]]
A = np.array([[1, 2, 3], [4, 5, 6]])
print("------------- A:")
print(A)
print("A.prod() :", A.prod()) # effectue le produit
print("A.cumprod():",A.cumprod()) # effectue le produit cumulé
------------- A: [[1 2 3] [4 5 6]] A.prod() : 720 A.cumprod(): [ 1 2 6 24 120 720]
A = np.array([[1, 2, 3], [4, 5, 6]])
print("------------- A:")
print(A)
print("A.min():",A.min()) # trouve le minimum du tableau
print("A.max():",A.max()) # trouve le maximum du tableau
------------- A: [[1 2 3] [4 5 6]] A.min(): 1 A.max(): 6
print("A.min():",A.min(axis=0)) # trouve le minimum / colonne du tableau
A.min(): [1 2 3]
print("A.max():",A.max(axis=1)) # trouve le max / ligne du tableau
A.max(): [3 6]
print("A.mean():",A.mean()) # calcule la moyenne
print("A.std():",A.std()) # calcule l'ecart type,
print("A.var():",A.var()) # calcule la variance
A.mean(): 3.5 A.std(): 1.707825127659933 A.var(): 2.9166666666666665
print("A.mean():",A.mean(axis=0)) # calcule la moyenne / colonne
A.mean(): [2.5 3.5 4.5]
print("A.mean():",A.mean(axis=1)) # calcule la moyenne / ligne
A.mean(): [2. 5.]
Une méthode tres importante : la méthode argsort()
v = np.array([2, 9, 1, 0, 8, 7, 3]) # tableau aléatoire
print(v)
[2 9 1 0 8 7 3]
pos = v.argsort()
print(pos) # retourne les index pour trier le vecteur
[3 2 0 6 5 4 1]
vtr = v[pos]
print(vtr)
[0 1 2 3 7 8 9]
import time
import random
nbf = 1_000_000
a = np.array([random.randint(0,10) for i in range(nbf)])
b = a.copy()
deb = time.time()
a.sort()
fin = time.time()
print("temps sort() :",fin-deb)
temps sort() : 0.008445262908935547
deba = time.time()
pos = b.argsort()
vtr = b[pos]
fina = time.time()
print("temps argsort() :",fina-deba)
temps argsort() : 0.036273956298828125
A = np.random.randint(0, 10, [5, 5]) # tableau aléatoire
print(A)
[[0 4 6 2 4] [2 3 2 1 7] [8 2 6 3 0] [6 8 9 5 8] [4 1 5 3 3]]
print(A.argsort()) # retourne les index pour trier chaque ligne du tableau
[[0 3 1 4 2] [3 0 2 1 4] [4 1 3 2 0] [3 0 1 4 2] [1 3 4 0 2]]
print(A[:,0].argsort()) # retourne les index pour trier la colonne 0 de A
[0 1 4 3 2]
A = A[A[:,0].argsort(), :] # trie les colonnes du tableau selon la colonne 0.
A
array([[0, 4, 6, 2, 4],
[2, 3, 2, 1, 7],
[4, 1, 5, 3, 3],
[6, 8, 9, 5, 8],
[8, 2, 6, 3, 0]])- Statistics
Correlation de Pearson :
import numpy as np
B = np.random.randn(3, 3) # nombres aléatoires 3x3
print("B :\n",B)
B : [[-1.50431309 -0.47709981 0.37929429] [-1.37681216 -0.60380522 0.9000462 ] [ 0.46200969 0.06868264 -0.52351756]]
# retourne la matrice de corrélation de B
print("np.corrcoef(B):\n",np.corrcoef(B))
np.corrcoef(B): [[ 1. 0.97238515 -0.98587208] [ 0.97238515 1. -0.99773884] [-0.98587208 -0.99773884 1. ]]
# retourne la matrice de corrélation entre les lignes 0 et 1 ou 2 de B
print(np.corrcoef(B[0,:], B[1,:]))
print(np.corrcoef(B[0,:], B[2,:]))
[[1. 0.97238515] [0.97238515 1. ]] [[ 1. -0.98587208] [-0.98587208 1. ]]
# retourne la matrice de corrélation entre les colonnes 0 et 1 de B
print(np.corrcoef(B[:,0], B[:, 1]))
[[1. 0.10031005] [0.10031005 1. ]]
np.unique() :
np.random.seed(0)
A = np.random.randint(0, 50, [5,5])
A
array([[44, 47, 0, 3, 3],
[39, 9, 19, 21, 36],
[23, 6, 24, 24, 12],
[ 1, 38, 39, 23, 46],
[24, 17, 37, 25, 13]])np.unique(A)
array([ 0, 1, 3, 6, 9, 12, 13, 17, 19, 21, 23, 24, 25, 36, 37, 38, 39,
44, 46, 47])values, counts = np.unique(A, return_counts=True)
for i, j in zip(values[counts.argsort()], counts[counts.argsort()]):
print(f'valeur {i:2} apparait {j}')
valeur 0 apparait 1 valeur 44 apparait 1 valeur 38 apparait 1 valeur 37 apparait 1 valeur 36 apparait 1 valeur 25 apparait 1 valeur 46 apparait 1 valeur 19 apparait 1 valeur 21 apparait 1 valeur 13 apparait 1 valeur 12 apparait 1 valeur 9 apparait 1 valeur 6 apparait 1 valeur 1 apparait 1 valeur 17 apparait 1 valeur 47 apparait 1 valeur 23 apparait 2 valeur 3 apparait 2 valeur 39 apparait 2 valeur 24 apparait 3
Calculs statistiques en présence de données manquates (NaN)
A = np.random.randn(5, 5)
A[0, 2] = np.nan # insere un NaN dans la matrice A
A[2, 4] = np.nan # insere un NaN dans la matrice A
print(A)
[[ 1.2206081 -1.33949555 nan -0.12346315 1.41437719] [-0.12405066 2.00815709 0.22988654 0.60489373 1.62715982] [ 1.59456053 0.23043417 -0.06491034 -0.96898025 nan] [-0.7827755 -0.44423283 -0.34518616 -0.88180055 -0.44265324] [-0.5409163 -1.32322737 -0.11279892 0.90734594 0.81526991]]
print(np.isnan(A))
[[False False True False False] [False False False False False] [False False False False True] [False False False False False] [False False False False False]]
nb_nan = np.isnan(A).sum()
print(nb_nan)
2
print('ratio NaN/zise:', (nb_nan/A.size)) # calcule la proportion de NaN dans A
ratio NaN/zise: 0.08
print('moyenne :', np.mean(A)) # calcule la moyenne de A
moyenne : nan
B = np.array([[1, 2, np.nan],
[4, 5, 6]])
print(np.nanmean(B)) # 3.6
print(np.nanmean(B, 0)) # [2.5, 3.5, 6.]
print(np.nanmean(B, 1)) # [1.5, 5.0]
3.6 [2.5 3.5 6. ] [1.5 5. ]
print('moyenne sans NaN:', np.nanmean(A)) # calcule la moyenne de A en ignorant les NaN
moyenne sans NaN: 0.13731313910742102
Valeurs propres et vecteurs propres
A = np.random.randint(0, 10, [3, 3])
print(A)
[[7 9 9] [3 6 7] [2 0 3]]
determ = np.linalg.det(A)
print('det =', determ) # calcule le determinant de A
det = 62.99999999999999
determ = np.around(determ)
print(determ)
63.0
# exemple :
import numpy as np
x = 1.1234567891234567
print(np.around(x, decimals=9)) # 1.1234567891
1.123456789
B = np.linalg.inv(A)
print('inv A:\n', B) # calcul l'inverse de A
inv A: [[ 0.28571429 -0.42857143 0.14285714] [ 0.07936508 0.04761905 -0.34920635] [-0.19047619 0.28571429 0.23809524]]
C = np.around(B, decimals=5)
print(C)
[[ 0.28571 -0.42857 0.14286] [ 0.07937 0.04762 -0.34921] [-0.19048 0.28571 0.2381 ]]
print(10*C[0,0])
2.8571
A = np.array([[4, -2],
[1, 1]])
print(A)
[[ 4 -2] [ 1 1]]
val, vect = np.linalg.eig(A)
print("Valeurs propres :", val)
print("Vecteurs propres :\n", vect)
Valeurs propres : [3. 2.] Vecteurs propres : [[0.89442719 0.70710678] [0.4472136 0.70710678]]
numVect = 1
print(A@vect[:,numVect])
print(val[numVect]*vect[:,numVect])
[1.41421356 1.41421356] [1.41421356 1.41421356]
3. Broadcasting:
Technique permetant d’effectuer des opérations entre tableaux de formes différentes, sans copier les données, en étendant automatiquement les dimensions pour qu’elles soient compatibles
import numpy as np
A = np.array([np.arange(5*i, 5*i+3) for i in range(2)])
print(A)
[[0 1 2] [5 6 7]]
B = 3
print("A :\n",A)
print("A+B :")
print(A+B) # résultat 1
A : [[0 1 2] [5 6 7]] A+B : [[ 3 4 5] [ 8 9 10]]
C = np.array([[3],[4]])
print("A:\n", A)
print("C:\n", C)
print(C.shape)
A: [[0 1 2] [5 6 7]] C: [[3] [4]] (2, 1)
print("A+C:")
print(A+C)
A+C: [[ 3 4 5] [ 9 10 11]]
L = np.array([13,6,2])
print(A)
print(L)
print(L.shape)
[[0 1 2] [5 6 7]] [13 6 2] (3,)
print(A+L)
[[13 7 4] [18 12 9]]
- Attention (2,) ≠ (2,1)
z = np.array([[5],[9]])
w = np.array([5, 9])
print(z.shape)
print(w.shape)
(2, 1) (2,)
print(A+z)
[[ 5 6 7] [14 15 16]]
print(A+w)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[36], line 1 ----> 1 print(A+w) ValueError: operands could not be broadcast together with shapes (2,3) (2,)
- solution
import numpy as np
a = np.array([1, 2, 3]) # shape = (3,)
a_col = a.reshape(-1, 1) # shape = (3, 1)
print(a.shape)
print(a_col.shape)
# print(np.eye(3,2)+a_col)
# print(np.eye(3,2)+a)
(3,) (3, 1)