🗂 Fichiers, 🔢 NumPy
- Fichier (intro)
- Fichier texte
- Fichier CSV
- Fichier JSON
- NumPy (intro)
- Tableaux NumPy
- Calcul vectorisé
- Bornes et correction
- Filtres et masques
- Restructurer sauvegarder
- NumPy et Matplotlib
- Activités
Un fichier c'est quoi?
- un ensemble de données stockées sur un support de stockage (disque dur, SSD, clé USB, carte SD, etc.)
- chaque fichier a un nom et une extension (par exemple
monfichier.txt) - les fichiers peuvent contenir différents types de données : texte, images, vidéos, audio, etc.
- pour lire ou écrire dans un fichier, on utilise des programmes ou des scripts
- chaque fichier utilise un encodage de caractères (le standard étant l'UTF-8).
- c'est un peu comme la « table de traduction » permettant à l'ordinateur de transformer les bits (0 et 1) en lettres et en accents.
- sans le bon encodage, le mot
"expérience"pourrait s'afficher comme"expérience". - c'est pourquoi il est important de toujours préciser
encoding="utf-8"dansopen()(ça s'en vient).
Types de fichiers courants (et exemples courants d'extensions)
- Fichiers texte (.txt, .csv, .json, .xml, etc.)
- Fichiers binaires (.bin, .exe, .dll, etc.)
- Fichiers image (.jpg, .png, .gif, etc.)
- Fichiers audio (.mp3, .wav, .flac, etc.)
- Fichiers vidéo (.mp4, .avi, .mkv, etc.)
Opérations courantes sur les fichiers
- Ouvrir un fichier : pour lire ou écrire des données
- Lire un fichier : pour extraire les données contenues dans le fichier
- Écrire dans un fichier : pour ajouter ou modifier des données dans le fichier
- Fermer un fichier : pour libérer les ressources utilisées par le fichier
open() et withEn Python, on utilise la fonction open() pour ouvrir un fichier.
Il est recommandé de l'utiliser avec le mot-clé with, qui garantit que le fichier est automatiquement fermé après utilisation, même en cas d'erreur.
with open("monfichier.txt", "r", encoding="utf-8") as f: # "r" pour mode lecture
contenu = f.read()
print(contenu)
# Le fichier est automatiquement fermé lorsqu'on sort du bloc with.
Les différents modes d'ouverture sont détaillés dans l'onglet Fichier texte.
Les explications de cette section étaient-elles claires ?
Un fichier texte est un type de fichier très courant et simple à manipuler.
- Il est simplement constitué d'une suite de caractères lisibles par l'humain.
- Il ne contient aucun formatage, juste du texte brut.
- Un fichier texte est organisé en lignes, séparées par des caractères spéciaux appelés sauts de ligne (
\n). - ✅ Les scripts Python (
.py) que vous écrivez sont aussi des fichiers texte. - ❌ Un fichier
.docx(Word) ou.pdfcontient du texte, mais aussi beaucoup d'autres informations de formatage, donc ce ne sont pas des fichiers texte.
On peut ouvrir ou créer un fichier texte à la main avec un éditeur de texte (Notepad, PyCharm, VSCode, ...) ou avec du code Python.
Lorsqu'on ouvre un fichier avec open(), on doit préciser ce qu'on veut faire avec lui en passant un mode :
| Mode | Signification | Effet |
|---|---|---|
| "r" | read — lecture | Lit le contenu du fichier |
| "w" | write — écriture | Crée ou écrase le fichier |
| "a" | append — ajout | Ajoute à la fin sans effacer |
📖 Mode "r" : Lecture
for ligne in fOn peut parcourir un fichier ouvert en mode lecture comme s'il s'agissait d'une liste de lignes, à l'aide d'une boucle for :
with open("monfichier.txt", "r", encoding="utf-8") as f:
for ligne in f:
# On peut faire différentes choses avec chaque ligne.
# Par exemple, l'afficher seulement si elle contient le mot "gros" :
if "gros" in ligne:
print(ligne, end="") # end="" pour éviter d'ajouter un 2e retour de ligne \n à la fin
# Ou encore calculer et afficher sa longueur (en caractères) :
print(f"Longueur de la ligne : {len(ligne)} caractères")
read()Supposons que le fichier monfichier.txt contient :
Y a pas deux gros.
Y en a qu'un seul.
Et il est pas gros.
with open("monfichier.txt", "r", encoding="utf-8") as f:
contenu = f.read()
print(contenu)
La variable contenu contiendra alors la chaîne de caractères complète du fichier, y compris les sauts de ligne :
Y a pas deux gros.
Y en a qu'un seul.
Et il est pas gros.
readlines()with open("monfichier.txt", "r", encoding="utf-8") as f:
lignes = f.readlines()
print(lignes)
La variable lignes contiendra une liste de chaînes de caractères, chaque chaîne représentant une ligne du fichier, avec les sauts de ligne (\n) inclus :
["Y a pas deux gros.\n", "Y en a qu'un seul.\n", "Et il est pas gros.\n"]
Pour retirer les \n, on peut utiliser la méthode strip() qui retire les espaces et sauts de ligne en début et en fin de chaque chaîne.
C'est l'occasion parfaite d'utiliser une compréhension de liste :
with open("monfichier.txt", "r", encoding="utf-8") as f:
lignes = [ligne.strip() for ligne in f.readlines()]
print(lignes)
Résultat :
["Y a pas deux gros.", "Y en a qu'un seul.", "Et il est pas gros."]
✏️ Mode "w" : Écriture
write()with open("monfichier.txt", "w", encoding="utf-8") as f:
f.write("Bonjour le monde!\n")
f.write("Ceci est un fichier texte.\n")
Plutôt que d'écrire ligne par ligne, on peut aussi construire une liste puis utiliser join() :
lignes = ["Y a pas deux gros.", "Y en a qu'un seul.", "Et il est pas gros."]
with open("monfichier.txt", "w", encoding="utf-8") as f:
f.write("\n".join(lignes))
La fonction join() prend une liste de chaînes et les combine en une seule chaîne, en insérant le séparateur (ici \n) entre chaque élément.
⚠️ATTENTION : Le mode "w" écrase le contenu existant à chaque ouverture. Si le fichier monfichier.txt existait déjà, il sera écrasé, c'est-à-dire effacé et remplacé par le nouveau contenu.
➕ Mode "a" : Ajout (append)
write() avec "a"Si on veut ajouter des données à la fin d'un fichier sans effacer ce qui s'y trouve déjà, on utilise le mode "a".
Imaginons un fichier journal.txt qui enregistre les héros qui complètent un niveau, au fur et à mesure :
# Première exécution — crée le fichier et écrit la première ligne
with open("journal.txt", "a", encoding="utf-8") as f:
f.write("Mario a complété le niveau 1.\n")
# Deuxième exécution — ajoute à la fin sans effacer
with open("journal.txt", "a", encoding="utf-8") as f:
f.write("Link a complété le niveau 1.\n")
# Troisième exécution — ajoute encore
with open("journal.txt", "a", encoding="utf-8") as f:
f.write("Kirby a complété le niveau 1.\n")
Après ces trois exécutions, journal.txt contiendra :
Mario a complété le niveau 1.
Link a complété le niveau 1.
Kirby a complété le niveau 1.
Si on avait utilisé "w" à la place de "a", seule la dernière ligne aurait été conservée.
⚠️ Pourquoi toujours utiliser with?
Sans with, on doit fermer le fichier manuellement avec fichier.close().
Si une erreur survient avant cette ligne, le fichier reste ouvert et les données peuvent être corrompues ou l'accès au fichier bloqué.
# ❌ À éviter
fichier = open("monfichier.txt", "r", encoding="utf-8")
contenu = fichier.read()
# Si une erreur survient ici, fichier.close() ne sera jamais appelée!
fichier.close()
# ✅ Avec with : le fichier est toujours fermé, même en cas d'erreur
with open("monfichier.txt", "r", encoding="utf-8") as f:
contenu = f.read()
# Automatiquement fermé ici, quoi qu'il arrive
🚨 Erreur fréquente : fichier introuvable
FileNotFoundError : le fichier n'existe pasSi le nom ou le chemin du fichier est mal écrit, Python lève une FileNotFoundError :
with open("monfichierr.txt", "r", encoding="utf-8") as f: # faute de frappe!
contenu = f.read()
FileNotFoundError: [Errno 2] No such file or directory: 'monfichierr.txt'
Cette erreur survient uniquement en mode lecture ("r"). En mode écriture ("w") ou ajout ("a"), Python crée le fichier automatiquement s'il n'existe pas.
Pour l'éviter, vérifiez :
- que le nom du fichier est écrit correctement (majuscules, extension, fautes de frappe)
- que le fichier se trouve dans le même dossier que votre script Python
Ouvrir, lire et écrire un fichier texte avec with open(...). Le fichier est automatiquement fermé à la fin du bloc.
| Opération | Syntaxe | Description |
|---|---|---|
| Ouvrir en lecture | with open("f.txt", "r", encoding="utf-8") as f: | Lit le contenu existant |
| Ouvrir en écriture | with open("f.txt", "w", encoding="utf-8") as f: | Écrase le contenu existant |
| Ouvrir en ajout | with open("f.txt", "a", encoding="utf-8") as f: | Ajoute à la fin sans effacer |
| Lire tout | contenu = f.read() | Retourne une seule chaîne (string) |
| Lire en liste | lignes = f.readlines() | Retourne une liste de strings (avec \n) |
| Lire ligne par ligne | for ligne in f: | Itère sur chaque ligne |
| Retirer les sauts de ligne | ligne.strip() | Retire \n en début et fin |
| Écrire | f.write("texte\n") | Écrit une chaîne dans le fichier |
Les explications de cette section étaient-elles claires ?
Un fichier CSV (Comma-Separated Values) est un fichier texte qui organise des données sous forme de tableau.
- Chaque ligne représente un enregistrement.
- Les valeurs de chaque ligne sont séparées par un délimiteur. La virgule (
,) est le plus courant, mais certains fichiers utilisent le point-virgule (;), la tabulation (touche Tab, ou\t), ou même l'espace (). C'est pourquoi on parle parfois de fichiers délimités plutôt que strictement CSV. - C'est l'un des formats les plus utilisés pour échanger des données tabulaires : tableurs, bases de données, résultats d'expériences, etc.
Exemple de contenu d'un fichier mesures.csv :
experience,tentative,ph_mesure,reaction_observee
Acide-base,1,4.7,True
Acide-base,2,5.1,True
Acide-base,3,6.9,False
Dans cette rencontre, l'objectif est surtout de comprendre ce qu'est un fichier CSV et comment Python peut le lire. Les bibliothèques NumPy et Pandas seront utilisées plus tard dans le cours pour manipuler et analyser des données plus efficacement.
👉 Il n'est donc pas nécessaire d'exécuter tous les exemples qui suivent : il suffit d'en comprendre le fonctionnement général.
Il existe plusieurs façons de lire un fichier CSV en Python. Le choix dépend surtout de ce qu'on veut faire avec les données.
Rappel : il n'est pas nécessaire d'exécuter ces exemples, l'objectif est surtout d'en comprendre le fonctionnement.
À partir du fichier mesures.csv :
experience,tentative,ph_mesure,reaction_observee
Acide-base,1,4.7,True
Acide-base,2,5.1,True
Acide-base,3,6.9,False
On pourrait lire les données de plusieurs façons.
1. À la main, comme un fichier texte
✅ Inclus avec Python — aucune installation requise.
with open("mesures.csv", "r", encoding="utf-8") as fichier:
for ligne in fichier: # Boucle sur toutes les lignes du fichier
valeurs = ligne.strip().split(",")
print(valeurs)
Résultat :
['experience', 'tentative', 'ph_mesure', 'reaction_observee']
['Acide-base', '1', '4.7', 'True']
['Acide-base', '2', '5.1', 'True']
['Acide-base', '3', '6.9', 'False']
Mais comment chaque ligne de texte est-elle devenue une liste? Tout se joue dans valeurs = ligne.strip().split(",").
Suivons la transformation étape par étape, en prenant la 3e liste affichée ci-dessus (['Acide-base', '2', '5.1', 'True']) :
# Étape 1 — la ligne lue dans le fichier contient un saut de ligne "\n" à la fin :
# "Acide-base,2,5.1,True\n"
#
# Étape 2 — .strip() retire les espaces et les saut de lignes présents :
# "Acide-base,2,5.1,True"
#
# Étape 3 — .split(",") coupe la chaîne à chaque virgule et retourne une LISTE :
#
# "Acide-base,2,5.1,True"
# │ │ │ │
# │ │ │ └─────────┐
# │ │ └──────┐ │
# │ └───┐ │ │
# │ │ │ │
# ▼ ▼ ▼ ▼
# ['Acide-base', '2', '5.1', 'True']
#
# ⚠️ Chaque valeur est une CHAÎNE de caractères (notez les guillemets),
# même les nombres : '2' et '5.1' ne sont PAS encore des nombres.
Cette méthode permet de comprendre qu'un fichier CSV est d'abord un simple fichier texte.
Par contre, il faut tout gérer soi-même : séparer les valeurs, ignorer l'en-tête, convertir les nombres, traiter les erreurs, etc.
2. Avec le module csv de Python
✅ Inclus avec Python — aucune installation requise.
import csv
with open("mesures.csv", "r", encoding="utf-8") as fichier:
lecteur = csv.reader(fichier)
for ligne in lecteur:
print(ligne)
Résultat :
['experience', 'tentative', 'ph_mesure', 'reaction_observee']
['Acide-base', '1', '4.7', 'True']
['Acide-base', '2', '5.1', 'True']
['Acide-base', '3', '6.9', 'False']
Le module csv est inclus avec Python. Il gère mieux la lecture des lignes et des séparateurs qu'une lecture entièrement manuelle.
Cependant, les valeurs sont encore lues comme du texte. Il faut donc convertir soi-même les nombres, les booléens ou les dates au besoin.
3. Avec NumPy
📦 Bibliothèque externe — à installer avec pip install numpy.
import numpy as np
donnees = np.genfromtxt(
"mesures.csv",
delimiter=",",
names=True,
dtype=None,
encoding="utf-8"
)
print(donnees)
Résultat :
[('Acide-base', 1, 4.7, True) ('Acide-base', 2, 5.1, True)
('Acide-base', 3, 6.9, False)]
NumPy peut lire des fichiers CSV, surtout lorsqu'ils contiennent principalement des données numériques.
C'est pratique pour faire des calculs efficacement, lorsque toutes les valeurs sont du même type, par exemple des float, mais moins agréable lorsque les colonnes contiennent des types variés, comme du texte, des nombres et des valeurs booléennes.
4. Avec Pandas
📦 Bibliothèque externe — à installer avec pip install pandas.
import pandas as pd
df = pd.read_csv("mesures.csv")
print(df)
Résultat :
experience tentative ph_mesure reaction_observee
0 Acide-base 1 4.7 True
1 Acide-base 2 5.1 True
2 Acide-base 3 6.9 False
Pandas est plus pratique pour travailler avec des fichiers CSV qui contiennent toutes sortes de données (des mesures, des catégories, etc.). Plus tard dans le cours, nous verrons en détail la bibliothèque Pandas. Il charge les données dans un tableau structuré appelé DataFrame, reconnaît souvent automatiquement les types de données et facilite ensuite le filtrage, le tri, les calculs et les visualisations.
Comparaison rapide
| Méthode | Installation | Avantage principal | Limite principale |
|---|---|---|---|
| Lecture manuelle | ✅ Aucune | Permet de comprendre la structure du fichier, Permet un contrôle total (parfois utile) | Il faut tout gérer soi-même |
Module csv | ✅ Aucune | Inclus avec Python et adapté aux fichiers CSV simples | Les valeurs restent principalement du texte |
| NumPy | 📦 pip install numpy | Très utile pour les données numériques (par exemple tous des float) | Moins pratique pour les tableaux avec des types variés |
| Pandas | 📦 pip install pandas | Très pratique pour analyser des données tabulaires | Bibliothèque externe à installer |
Les explications de cette section étaient-elles claires ?
Le JSON (JavaScript Object Notation) est un format de fichier texte conçu pour stocker et échanger des données structurées.
- Il est lisible par les humains : on peut l'ouvrir dans n'importe quel éditeur de texte et comprendre son contenu d'un coup d'œil.
- Il est facile à utiliser avec Python : le module
json(inclus avec Python, aucune installation nécessaire) permet de lire et d'écrire du JSON en quelques lignes. - Il supporte les mêmes types que Python : chaînes, nombres, booléens, listes et dictionnaires.
Un fichier .txt contient du texte brut sans structure. Si on veut sauvegarder plusieurs informations liées entre elles (par exemple le profil d'un joueur avec son nom, son score et ses niveaux complétés), il faut inventer soi-même une façon d'organiser les données, et la relire devient vite compliqué.
Le JSON résout ce problème : il sauvegarde directement la structure des données (dictionnaires, listes imbriquées) et Python peut la reconstruire automatiquement à la lecture.
import json
json.dump()Imaginons qu'on veuille sauvegarder les données d'une expérience en laboratoire :
import json
experience = {
"nom": "Réaction acide-base",
"tentative": 3,
"ph_mesure": 4.7,
"reaction_observee": True,
"reactifs": ["HCl", "NaOH", "eau distillée"]
}
with open("experience.json", "w", encoding="utf-8") as f:
json.dump(experience, f, indent=4, ensure_ascii=False)
Le fichier experience.json contiendra alors :
{
"nom": "Réaction acide-base",
"tentative": 3,
"ph_mesure": 4.7,
"reaction_observee": true,
"reactifs": ["HCl", "NaOH", "eau distillée"]
}
💡 L'argument indent=4 ajoute des indentations pour rendre le fichier plus lisible. Sans lui, tout serait sur une seule ligne.
💡 L'argument ensure_ascii=False permet de conserver les caractères spéciaux (comme les accents) tels quels, au lieu de les convertir en séquences d'échappement ASCII. Le fichier JSON restera ainsi plus lisible.
json.load()Pour récupérer les données sauvegardées et les utiliser dans Python, on utilise json.load().
Le résultat est directement un dictionnaire Python, prêt à être utilisé.
import json
with open("experience.json", "r", encoding="utf-8") as f:
experience = json.load(f)
print(f"Expérience : {experience['nom']}") # Expérience : Réaction acide-base
print(f"Tentative #{experience['tentative']}") # Tentative #3
print(f"pH mesuré : {experience['ph_mesure']}") # pH mesuré : 4.7
print(f"Réaction observée : {experience['reaction_observee']}") # Réaction observée : True
print(f"Réactifs : {experience['reactifs']}") # Réactifs : ['HCl', 'NaOH', 'eau distillée']
👉 On accède aux valeurs exactement comme dans n'importe quel dictionnaire Python, parce que c'en est un!
Le JSON ressemble beaucoup à la syntaxe Python, et ce n'est pas un hasard : les deux utilisent des accolades {} pour les structures clé-valeur et des crochets [] pour les listes. Si on sait déjà lire du Python, un fichier JSON semblera familier du premier coup d'œil.
Par contre, JSON est un format d'échange universel (pas lié à Python), donc il a ses propres règles strictes :
| Python | JSON |
|---|---|
| True / False | true / false (minuscules) |
| None | null |
| Guillemets simples 'abc' acceptés | Seulement guillemets doubles "abc" |
| Tuples (1, 2) | Pas de tuples, convertis en listes [1, 2] |
| Commentaires # ... | Pas de commentaires |
La bonne nouvelle : json.dump() et json.load() gèrent toutes ces conversions automatiquement.
On écrit du Python, Python traduit en JSON, et vice-versa. On n'a pas à s'en préoccuper, ni à le retenir.
Le format JSON est particulièrement utile dans le cours 420-4A4 : Réseaux de neurones et sciences, où il est utilisé pour conserver les hyperparamètres des réseaux de neurones entre les expériences (taux d'apprentissage, nombre de couches, taille des lots, etc.).
| Situation | Format recommandé |
|---|---|
| Données simples, ligne par ligne | Fichier texte (.txt) |
| Données structurées (dictionnaires, listes imbriquées) | JSON (.json) |
| Données tabulaires (tableau de valeurs) | CSV (.csv) |
Sauvegarder et relire des structures Python (dictionnaires, listes) avec le module import json, inclus avec Python.
| Opération | Syntaxe | Description |
|---|---|---|
| Importer | import json | Module inclus, aucune installation requise |
| Sauvegarder | json.dump(data, f, indent=4, ensure_ascii=False) | Écrit un objet Python dans un fichier JSON |
| Charger | data = json.load(f) | Lit un objet Python à partir d'un fichier JSON |
Les explications de cette section étaient-elles claires ?
📣 NumPy se prononce nomme-paille
Jusqu’ici, pour travailler avec une liste de nombres, il fallait utiliser des boucles for : une itération par élément, une opération à la fois.
Ça fonctionne, mais c’est lent et verbeux dès qu’on manipule des milliers de valeurs.
C’est là qu’intervient 🔢 NumPy : une bibliothèque Python conçue pour effectuer des calculs sur des tableaux en une seule instruction, sans boucle, et à une vitesse bien supérieure!
| Onglet | Ce qu’on y apprend |
|---|---|
| Tableaux NumPy | Créer un tableau, comprendre shape et dtype |
| Calcul vectorisé | Appliquer une opération à tout un tableau sans boucle |
| Bornes et correction | Encadrer des valeurs avec clip(), maximum(), minimum() |
| Filtres et masques | Filtrer, vérifier et transformer selon des conditions |
| Restructurer sauvegarder | Restructurer, combiner, générer aléatoirement, sauvegarder |
| NumPy et Matplotlib | Tracer des graphiques à partir de tableaux NumPy |
NumPy n’est qu’une des bibliothèques Python très utilisées en sciences.
Pour votre culture générale, voici comment elle s’inscrit dans l’écosystème Python scientifique :
- 🔢 NumPy : calcul sur des tableaux numériques - c’est le sujet de ces onglets
- 🐼 Pandas : manipulation de données tabulaires - sera vue à la rencontre 11
- 📊 Matplotlib : visualisation de données - on la connait déjà
- 🤖 Scikit-learn : apprentissage automatique - un aperçu à la rencontre 15
- 🧠 Keras / TensorFlow : apprentissage profond - utilisées dans le cours Réseaux de neurones
NumPy n’est pas inclus avec Python. Il faut l’installer avant de pouvoir l’utiliser.
Consulter la recette d’installation de bibliothèques pour savoir comment faire, ou exécuter cette commande dans le terminal :
pip install numpy
Les explications de cette section étaient-elles claires ?
En Python, une liste peut contenir n’importe quoi : des nombres, des strings, des listes, des objets mélangés.
ma_liste = [1, "deux", 3.0, [4, 5], {"six": 6}]
C’est très flexible, mais cette flexibilité a un coût : Python doit vérifier le type de chaque élément un par un.
Un tableau NumPy (ndarray) est différent : tous ses éléments ont le même type.
NumPy tire profit de cette contrainte pour effectuer des calculs beaucoup plus rapidement, en traitant le tableau entier d’un seul bloc plutôt qu’élément par élément.
La convention universelle est d’importer NumPy avec l’alias np :
import numpy as np
Vous verrez import numpy as np au début de tous les scripts qui utilisent NumPy. C’est une convention que tout le monde respecte. Utilisez-la aussi.
Il existe plusieurs façons de créer un tableau selon le contexte :
À partir d’une liste existante :
liste = [1, 2, 3, 4, 5]
tab_numpy = np.array(liste)
print(tab_numpy) # [1 2 3 4 5]
print(type(tab_numpy)) # <class ‘numpy.ndarray’>
Avec des valeurs prédéfinies :
zeros = np.zeros(5) # [0. 0. 0. 0. 0.] 5 zéros (initialiser un tableau vide)
uns = np.ones(5) # [1. 1. 1. 1. 1.] 5 uns
neufs = np.full(5, 9) # [9 9 9 9 9] 5 fois la valeur 9
Avec des séquences de valeurs :
sequence = np.arange(0, 10, 2) # [0 2 4 6 8] entiers de 0 à 9 par pas de 2
# (fonctionne comme la fonction range())
intervalle = np.linspace(0, 1, 5) # [0. 0.25 0.5 0.75 1. ] 5 valeurs régulièrement espacées entre 0 et 1
💡 La différence clé entre np.arange() et np.linspace() :
- avec
np.arange()on choisit le pas entre chaque valeur - avec
np.linspace()on choisit le nombre de points souhaité.
Pour les graphiques, np.linspace() est presque toujours préférable, car on sait exactement combien de points on aura.
liste = [1, 2, 3, 4, 5]
tab_numpy = np.array(liste)
print(liste) # [1, 2, 3, 4, 5]
print(tab_numpy) # [1 2 3 4 5]
print(type(liste)) # <class 'list'>
print(type(tab_numpy)) # <class 'numpy.ndarray'>
Les valeurs sont les mêmes, mais NumPy retire les virgules à l'affichage. Le type() confirme qu'il s'agit bien de deux objets différents — une list Python et un ndarray NumPy.
shape et dtype : deux propriétés essentiellesCe sont les deux premières choses à vérifier sur un tableau inconnu.
shape - la forme du tableau (ses dimensions), sous forme de tuple :
tab_1d = np.array([10, 20, 30, 40, 50])
print(tab_1d.shape) # (5,) tableau 1D de 5 éléments
NumPy supporte les tableaux à plusieurs dimensions. Un tableau 2D ressemble à une grille (lignes et colonnes) :
tab_2d = np.array([[1, 2, 3],
[4, 5, 6]])
print(tab_2d.shape) # (2, 3) 2 lignes, 3 colonnes
Dans ce cours, nous travaillerons presque exclusivement avec des tableaux 1D. Les tableaux 2D seront davantage utilisés dans les cours suivants (Réseaux de neurones, Projet scientifique), mais il est bon de savoir que NumPy peut gérer des tableaux de n'importe quelle dimension (2D, 42D, ...).
size - le nombre total d’élémentsprint(tab_2d.size) # 6 (2 lignes x 3 colonnes)
dtype - le type des données stockées :
tab_entiers = np.array([1, 2, 3])
tab_decimaux = np.array([1.0, 2.0, 3.0])
tab_booleens = np.array([True, False, True])
print(tab_entiers.dtype) # int64 entiers
print(tab_decimaux.dtype) # float64 décimaux
print(tab_booleens.dtype) # bool booléens
Si on crée un tableau avec par exemple à la fois des nombres entiers et des nombres décimaux, NumPy choisit automatiquement le type le plus général :
tab_mixte = np.array([1, 2, 3.0])
print(tab_mixte.dtype) # float64 NumPy a converti tous les entiers en décimaux
print(tab_mixte) # [1. 2. 3.] Les décimaux sont affichés avec un point décimal
C’est souvent le comportement voulu, mais il faut en être conscient.
shape, size et dtype sont des propriétésNotez bien que shape, size et dtype sont des propriétés du tableau, pas des fonctions.
On les appelle sans parenthèses, contrairement à une fonction :
nb_elements = tab_1d.size # Correct : nb_elements contient le nombre d'éléments
nb_elements = tab_1d.size() # Incorrect : TypeError, car size n'est pas une fonction
On accède aux éléments d’un tableau exactement comme pour une liste Python :
tableau = np.array([10, 20, 30, 40, 50])
print(tableau[0]) # 10 → premier élément
print(tableau[-1]) # 50 → dernier élément
print(tableau[1:4]) # [20 30 40] → éléments de l'index 1 (inclus) à l'index 4 (exclus)
| Opération | Syntaxe | Description |
|---|---|---|
| Importer NumPy | import numpy as np | Convention universelle |
| Depuis une liste | tab_numpy = np.array([1, 2, 3]) | Convertit une liste en tableau |
| Tableau de zéros | tab_numpy = np.zeros(5) | Tableau de 5 zéros (float64) |
| Tableau de uns | tab_numpy = np.ones(5) | Tableau de 5 uns (float64) |
| Tableau avec valeur fixe | tab_numpy = np.full(5, 9) | Tableau de 5 neufs |
| Séquence entière | tab_numpy = np.arange(0, 10, 2) | [0 2 4 6 8] comme range() |
| Séquence espacée | tab_numpy = np.linspace(0, 1, 5) | 5 valeurs entre 0 et 1 (inclus) |
| Forme du tableau | forme = tab_numpy.shape | Retourne (lignes, colonnes) |
| Type des données | type_donnees = tab_numpy.dtype | Ex : float64, int64, bool |
| Nombre d'éléments | nb_elements = tab_numpy.size | Nombre total d'éléments |
| Accès par indice | element = tab_numpy[2] | 3e élément (indice commence à 0) |
| Sous-tableau | sous_tab = tab_numpy[1:4] | Éléments d'indices 1, 2, 3 |
Les explications de cette section étaient-elles claires ?
En Python ordinaire, pour ajouter 5 à toutes les valeurs d’une liste, on doit écrire une boucle :
# Avec une liste Python : une boucle obligatoire
valeurs = [10, 20, 30, 40, 50]
doubles = [v + 5 for v in valeurs] # [15, 25, 35, 45, 55]
Avec NumPy, l’opération s’applique à tout le tableau d’un seul coup, sans boucle :
# Avec NumPy : une seule ligne, bien plus rapide
import numpy as np
valeurs = np.array([10, 20, 30, 40, 50])
doubles = valeurs + 5 # [15 25 35 45 55]
C’est ce qu’on appelle la vectorisation : NumPy effectue l’opération sur tous les éléments simultanément.
Sur de petites listes la différence de vitesse est imperceptible, mais sur des millions de valeurs, elle devient dramatique. Voici un exemple concret avec la mesure du temps de calcul pour doubler une liste de 1 million de valeurs :
import numpy as np
import time
n = 1_000_000 # 1 million de valeurs
# Avec une liste Python
valeurs_liste = list(range(n))
debut = time.time()
doubles_liste = [v * 2 for v in valeurs_liste]
print(f"Boucle Python : {time.time() - debut:.4f} secondes")
# Avec NumPy
valeurs_numpy = np.arange(n)
debut = time.time()
doubles_numpy = valeurs_numpy * 2
print(f"NumPy : {time.time() - debut:.4f} secondes")
Le résultat typique ressemble à :
Boucle Python : 0.0850 secondes
NumPy : 0.0012 secondes
NumPy est environ 70 fois plus rapide sur cet exemple. L’écart grandit encore sur des opérations plus complexes.
Tous les opérateurs habituels (+, -, *, /, **) s’appliquent élément par élément sur un tableau NumPy :
x = np.array([1, 2, 3, 4, 5])
print(x + 10) # [11 12 13 14 15]
print(x * 3) # [ 3 6 9 12 15]
print(x ** 2) # [ 1 4 9 16 25]
print(x / 2) # [0.5 1. 1.5 2. 2.5]
On peut aussi faire des opérations entre deux tableaux de même taille, et NumPy appliquera l’opération à chaque paire d’éléments correspondants :
a = np.array([1, 2, 3])
b = np.array([10, 20, 30])
print(a + b) # [11 22 33]
print(a * b) # [10 40 90]
NumPy fournit des versions vectorisées de toutes les fonctions mathématiques courantes. Elles s’appliquent à chaque élément du tableau sans boucle :
angles = np.linspace(0, np.pi, 5) # [0, π/4, π/2, 3π/4, π]
print(np.sin(angles)) # [0. 0.707 1. 0.707 0. ]
print(np.cos(angles)) # [1. 0.707 0. -0.707 -1. ]
valeurs = np.array([4.0, 9.0, 16.0, 25.0])
print(np.sqrt(valeurs)) # [2. 3. 4. 5.]
donnees = np.array([-3.7, 1.2, -0.5, 4.9])
print(np.abs(donnees)) # [3.7 1.2 0.5 4.9] valeur absolue : retire le signe négatif
print(np.floor(donnees)) # [-4. 1. -1. 4.] arrondi vers le bas (ex. -3.7 → -4, pas -3)
print(np.ceil(donnees)) # [-3. 2. 0. 5.] arrondi vers le haut (ex. -3.7 → -3, pas -4)
Ces fonctions calculent une valeur unique à partir de tout le tableau :
scores = np.array([72, 85, 61, 90, 78])
print(np.sum(scores)) # 386
print(np.mean(scores)) # 77.2
print(np.min(scores)) # 61
print(np.max(scores)) # 90
print(np.std(scores)) # 10.88 écart-type : mesure à quel point les valeurs s'éloignent de la moyenne
# (0 = toutes identiques, grand = très dispersées)
argmax() et argmin() : trouver l’indice du maximum/minimumPlutôt que de retourner la valeur maximale ou minimale, argmax() et argmin() retournent l’index de cet élément dans le tableau.
C’est utile pour retrouver quel élément a obtenu le meilleur (ou le pire) résultat.
scores = np.array([72, 85, 61, 90])
noms = ["Astro", "Peluche", "Chatmouraï", "Mini-boulette"]
indice_max = np.argmax(scores) # 3 Mini-boulette a le score le plus élevé
indice_min = np.argmin(scores) # 2 Chatmouraï a le score le plus bas
print(f"Meilleur score : {noms[indice_max]} avec {scores[indice_max]}")
# Meilleur score : Mini-boulette avec 90
argmax() vs max()np.max(scores) retourne 90 (la valeur).
np.argmax(scores) retourne 3 (la position).
Les deux sont utiles selon le contexte.
| Opération | Syntaxe | Description |
|---|---|---|
| Importer NumPy | import numpy as np | Convention universelle |
| Addition | tab_resultat = tab_numpy + 5 | Ajoute 5 à chaque élément |
| Multiplication | tab_resultat = tab_numpy * 2 | Multiplie chaque élément par 2 |
| Puissance | tab_resultat = tab_numpy ** 2 | Met chaque élément au carré |
| Addition élément par élément | tab_resultat = tab_a + tab_b | Additionne deux tableaux de même taille |
| Sinus | tab_resultat = np.sin(tab_numpy) | Calcule sin() sur chaque élément |
| Cosinus | tab_resultat = np.cos(tab_numpy) | Calcule cos() sur chaque élément |
| Racine carrée | tab_resultat = np.sqrt(tab_numpy) | Racine carrée de chaque élément |
| Valeur absolue | tab_resultat = np.abs(tab_numpy) | Valeur absolue de chaque élément |
| Exponentielle | tab_resultat = np.exp(tab_numpy) | e^x pour chaque élément |
| Arrondi inférieur | tab_resultat = np.floor(tab_numpy) | Arrondi vers le bas (ex. -3.7 devient -4) |
| Arrondi supérieur | tab_resultat = np.ceil(tab_numpy) | Arrondi vers le haut (ex. -3.7 devient -3) |
| Somme | total = np.sum(tab_numpy) | Somme de tous les éléments |
| Moyenne | moyenne = np.mean(tab_numpy) | Moyenne de tous les éléments |
| Minimum | minimum = np.min(tab_numpy) | Valeur minimale |
| Maximum | maximum = np.max(tab_numpy) | Valeur maximale |
| Écart-type | ecart = np.std(tab_numpy) | Mesure la dispersion (écart-type) |
| Indice du maximum | indice = np.argmax(tab_numpy) | Indice de la valeur la plus grande |
| Indice du minimum | indice = np.argmin(tab_numpy) | Indice de la valeur la plus petite |
Les explications de cette section étaient-elles claires ?
Dans de nombreuses situations réelles, les valeurs calculées ou mesurées peuvent dépasser des limites physiques ou logiques : une luminosité ne peut pas être négative ni dépasser 1, une coordonnée sur un écran ne peut pas sortir de la fenêtre, un pourcentage doit rester entre 0 et 100.
NumPy fournit des fonctions pour corriger ou encadrer automatiquement des valeurs hors limites, sans écrire de conditions if ni de boucles.
np.clip() - ramener des valeurs entre une borne minimum et un maximumOn utilise np.clip(tableau, min, max) quand on connait à l’avance deux bornes (un minimum ET un maximum) et qu'on veut garantir que toutes les valeurs restent dans cet intervalle en une seule instruction.
Pour chaque élément du tableau :
- si la valeur est inférieure à
min, elle devientmin; - si la valeur est supérieure à
max, elle devientmax; - sinon, elle reste inchangée.
Un capteur de pH mesure l’acidité d’une solution. Les valeurs valides se situent entre 0 et 14, mais le capteur peut retourner des valeurs aberrantes à cause du bruit de mesure. On veut corriger ces mesures avant de les analyser :
mesures_ph = np.array([-0.3, 4.2, 7.1, 14.8, 6.9])
mesures_valides = np.clip(mesures_ph, 0, 14)
print(mesures_valides) # [ 0. 4.2 7.1 14. 6.9]
La mesure -0.3 est ramenée à 0 et la mesure 14.8 est ramenée à 14. Les autres sont restées intactes.
np.maximum() et np.minimum() - appliquer une borne ou comparer deux tableauxLes fonctions np.maximum() et np.minimum() peuvent servir à deux choses différentes :
- appliquer une seule borne à un tableau;
- comparer deux tableaux position par position.
Contrairement à np.clip(), qui applique une borne minimale et une borne maximale en une seule instruction, np.maximum() et np.minimum() permettent de corriger seulement un côté à la fois.
1. Appliquer une borne avec une constante
On utilise np.maximum(tableau, valeur_min) pour imposer un minimum.
Autrement dit, chaque valeur plus petite que valeur_min est remplacée par valeur_min.
import numpy as np
intensites = np.array([-0.2, 0.0, 0.4, 0.8, 1.3])
intensites_sans_negatif = np.maximum(intensites, 0)
print(intensites_sans_negatif)
Résultat :
[0. 0. 0.4 0.8 1.3]
Ici, la valeur -0.2 est ramenée à 0. Les autres valeurs restent inchangées.
On utilise plutôt np.minimum(tableau, valeur_max) pour imposer un maximum.
Autrement dit, chaque valeur plus grande que valeur_max est remplacée par valeur_max.
intensites_limitees = np.minimum(intensites_sans_negatif, 1)
print(intensites_limitees)
Résultat :
[0. 0. 0.4 0.8 1. ]
Ici, la valeur 1.3 est ramenée à 1.
Dans cet exemple, les valeurs représentent une intensité normalisée, par exemple une luminosité ou une probabilité.
Elles devraient normalement rester entre 0 et 1, mais un calcul ou une mesure peut parfois produire une valeur légèrement hors limites.
On pourrait donc écrire :
intensites = np.array([-0.2, 0.0, 0.4, 0.8, 1.3])
intensites_corrigees = np.maximum(intensites, 0)
intensites_corrigees = np.minimum(intensites_corrigees, 1)
print(intensites_corrigees)
Résultat :
[0. 0. 0.4 0.8 1. ]
Cette méthode donne un résultat semblable à np.clip(intensites, 0, 1), mais en appliquant les deux bornes séparément.
2. Comparer deux tableaux position par position
np.maximum() et np.minimum() peuvent aussi comparer deux tableaux de même taille.
Dans ce cas :
np.maximum(tableau_a, tableau_b)prend la plus grande valeur à chaque position;np.minimum(tableau_a, tableau_b)prend la plus petite valeur à chaque position.
Par exemple, imaginons deux séries de mesures prises par deux capteurs différents :
capteur_a = np.array([12.1, 13.5, 11.8, 14.2])
capteur_b = np.array([12.4, 13.1, 12.0, 13.9])
mesures_max = np.maximum(capteur_a, capteur_b)
mesures_min = np.minimum(capteur_a, capteur_b)
print(mesures_max)
print(mesures_min)
Résultat :
[12.4 13.5 12. 14.2]
[12.1 13.1 11.8 13.9]
Le premier tableau contient donc, pour chaque position, la mesure la plus élevée des deux capteurs. Le deuxième tableau contient, pour chaque position, la mesure la plus basse.
Cela peut être utile lorsqu'on veut créer un tableau des extrêmes locaux entre deux séries de données : par exemple les valeurs les plus hautes et les plus basses mesurées par deux instruments, deux simulations ou deux scénarios.
np.max() vs np.maximum() : ne pas confondrevaleurs = np.array([3, 7, 1, 9, 4])
print(np.max(valeurs)) # 9 une seule valeur : le maximum du tableau
print(np.maximum(valeurs, 5)) # [5 7 5 9 5] un tableau : compare chaque élément à 5
np.max() résume le tableau en une valeur.
np.maximum() produit un nouveau tableau de même taille.
| Opération | Syntaxe | Description |
|---|---|---|
| Importer NumPy | import numpy as np | Convention universelle |
| Limiter entre un min et un max | tab_resultat = np.clip(tab_numpy, 0, 1) | Chaque valeur est ramenée entre 0 et 1 |
| Appliquer un minimum | tab_resultat = np.maximum(tab_numpy, 0) | Remplace les valeurs plus petites que 0 par 0 |
| Appliquer un maximum | tab_resultat = np.minimum(tab_numpy, 100) | Remplace les valeurs plus grandes que 100 par 100 |
| Maximum entre deux tableaux | tab_resultat = np.maximum(tab_a, tab_b) | Élément par élément, prend le plus grand |
| Minimum entre deux tableaux | tab_resultat = np.minimum(tab_a, tab_b) | Élément par élément, prend le plus petit |
Les explications de cette section étaient-elles claires ?
En sciences, on travaille rarement avec toutes les données en même temps. On veut souvent isoler les mesures qui dépassent un seuil, remplacer les valeurs aberrantes, ou classer les résultats selon une condition : par exemple garder seulement les températures au-dessus de 0°C, ou étiqueter les concentrations selon qu’elles sont en zone sûre ou non.
En Python ordinaire, chacune de ces opérations demande une boucle avec un if.
Avec NumPy, on exprime la condition directement sur le tableau entier en une seule ligne, peu importe s’il contient 10 ou 10 millions de valeurs.
Un masque booléen est un tableau de True et False de la même taille qu'un tableau de données.
Chaque True indique un élément qui satisfait la condition, chaque False un élément qui ne la satisfait pas.
valeurs = np.array([4, -2, 7, -1, 0, 3])
masque = valeurs < 0
print(masque) # [False True False True False False]
On peut ensuite utiliser ce masque pour extraire/filtrer les éléments qui satisfont la condition :
negatifs = valeurs[masque]
print(negatifs) # [-2 -1]
Ces deux blocs sont équivalents. Le raccourci est plus courant en pratique :
# Version avec masque intermédiaire
masque = valeurs < 0
negatifs = valeurs[masque]
# Version directe (raccourci)
negatifs = valeurs[valeurs < 0]
On peut combiner plusieurs conditions avec & (ET) et | (OU). Chaque condition doit être entre parenthèses.
tableau = np.array([5, 12, 18, 25, 30, 3])
# ET : les deux conditions vraies simultanément
entre_10_et_20 = tableau[(tableau >= 10) & (tableau <= 20)]
print(entre_10_et_20) # [12 18]
# OU : au moins une condition vraie
extremes = tableau[(tableau < 5) | (tableau > 25)]
print(extremes) # [30 3]
Si on crée d'abord un masque, il faut aussi des parenthèses autour de chaque condition lorsqu'il y en a plusieurs :
masque = (tableau >= 10) & (tableau <= 20)
entre_10_et_20 = tableau[masque]
np.any() et np.all() - vérifier des conditions globalesCes deux fonctions posent une question sur l’ensemble du tableau et retournent un seul True ou False :
np.any(condition): est-ce qu’au moins un élément satisfait la condition?np.all(condition): est-ce que tous les éléments satisfont la condition?
Par exemple, un chercheur a mesuré la pression atmosphérique à 6 stations météo. Avant d’analyser les données, il veut vérifier leur validité :
pressions = np.array([1012.3, 998.7, 1021.5, -5.0, 1008.1, 1015.4])
anomalie_detectee = np.any(pressions < 0) # Y a-t-il au moins une mesure invalide (pression négative)?
print(anomalie_detectee) # True → une valeur aberrante a été détectée
toutes_valides = np.all((pressions >= 900) & (pressions <= 1100)) # Toutes les mesures sont-elles dans une plage réaliste?
print(toutes_valides) # False → la valeur -5.0 sort de la plage
On utilise souvent ces fonctions dans un if pour stopper le traitement si les données sont invalides :
if np.any(pressions < 0):
print("Attention : des mesures invalides ont été détectées.")
else:
print("Toutes les mesures sont valides, analyse en cours.")
np.where() - choisir une valeur selon une conditionLe filtrage vu précédemment permet d'extraire des valeurs selon une condition. Mais parfois, on ne veut pas réduire le tableau : on veut produire un nouveau tableau de même taille, où chaque position reçoit une valeur selon une condition.
C'est exactement le rôle de np.where().
np.where() prend trois arguments :
np.where(condition, choix_si_vrai, choix_si_faux)
Pour chaque élément, NumPy pose la question de la condition :
- si la réponse est vraie, le résultat prend la valeur de
choix_si_vrai; - si la réponse est fausse, le résultat prend la valeur de
choix_si_faux.
Le tableau résultant a toujours la même taille que le tableau de départ.
Que peut-on mettre dans les deux choix?
Les deux choix peuvent être :
- une nouvelle valeur fixe;
- la valeur originale du tableau;
- une valeur provenant d’un autre tableau.
Par exemple :
# Remplacer certaines valeurs et garder les autres
corrigees = np.where(concentrations < 0, 0, concentrations)
# Même idée, mais avec la condition inversée
corrigees = np.where(concentrations >= 0, concentrations, 0)
# Choisir entre deux nouvelles valeurs
classification = np.where(mesures_ph < 7, "acide", "basique/neutre")
# Choisir entre deux tableaux
resultat = np.where(condition, tableau_a, tableau_b)
Dans tous les cas, NumPy fait le même travail : il choisit une valeur à chaque position.
Exemple 1 : remplacer certaines valeurs et garder les autres
Par exemple, un biologiste mesure des concentrations en solution.
Les valeurs négatives sont physiquement impossibles et doivent être remplacées par 0.
Les valeurs valides, elles, doivent rester telles quelles.
import numpy as np
concentrations = np.array([4.2, -0.3, 7.1, -1.5, 0.0, 3.8])
corrigees = np.where(concentrations < 0, # condition : est-ce que la valeur est négative?
0, # si oui : remplacer par 0
concentrations) # si non : garder la valeur d’origine
print(corrigees)
Résultat :
[4.2 0. 7.1 0. 0. 3.8]
Ici, les valeurs négatives sont remplacées par 0.
Les autres valeurs sont conservées.
On aurait aussi pu écrire la condition dans l’autre sens :
corrigees = np.where(concentrations >= 0, # condition : est-ce que la valeur est valide?
concentrations, # si oui : garder la valeur d’origine
0) # si non : remplacer par 0
Le résultat serait le même.
Exemple 2 : choisir entre deux nouvelles valeurs
Parfois, on ne veut pas garder les valeurs d’origine. On veut plutôt produire un nouveau tableau où chaque élément reçoit une nouvelle valeur selon la condition.
Par exemple, un technicien veut attribuer automatiquement une étiquette à chaque mesure de pH :
mesures_ph = np.array([3.1, 7.0, 8.5, 4.2, 6.9])
classification = np.where(mesures_ph < 7, # condition : est-ce que le pH est inférieur à 7?
"acide", # si oui : écrire "acide"
"basique/neutre") # si non : écrire "basique/neutre"
print(classification)
Résultat :
['acide' 'basique/neutre' 'basique/neutre' 'acide' 'acide']
Dans cet exemple, aucune valeur numérique d’origine n’est conservée. Chaque élément est remplacé par une nouvelle valeur.
Cette forme peut servir à créer des catégories, comme ici, mais aussi des codes numériques :
codes = np.where(mesures_ph < 7, 0, 1)
print(codes)
Résultat :
[0 1 1 0 0]
Exemple 3 : choisir entre deux tableaux
Les deux choix peuvent aussi être deux tableaux (de même taille).
Dans ce cas, NumPy choisit, à chaque position, une valeur provenant du premier ou du deuxième tableau.
mesures_a = np.array([10.2, 11.5, 9.8, 12.1])
mesures_b = np.array([10.0, 11.8, 10.1, 11.9])
utiliser_a = np.array([True, False, False, True])
resultat = np.where(utiliser_a, mesures_a, mesures_b)
print(resultat)
Résultat :
[10.2 11.8 10.1 12.1]
Pour chaque position :
- si
utiliser_avautTrue, NumPy prend la valeur demesures_a; - si
utiliser_avautFalse, NumPy prend la valeur demesures_b.
np.where() vs filtre : ne pas confondreFiltre t[t > 0] : le tableau résultant est plus court (seuls les éléments qui satisfont sont conservés).
np.where() : le tableau résultant a la même longueur (chaque élément reçoit une valeur selon la condition).
| Opération | Syntaxe | Description |
|---|---|---|
| Importer NumPy | import numpy as np | Convention universelle |
| Créer un masque | masque = tab_numpy > 0 | Tableau de booléens selon la condition |
| Filtrer avec un masque | tab_resultat = tab_numpy[masque] | Garde seulement les éléments qui satisfont |
| Filtrer directement | tab_resultat = tab_numpy[tab_numpy > 0] | Raccourci : filtre en une seule ligne |
| Filtre ET | tab_resultat = tab_numpy[(tab_numpy > 0) & (tab_numpy < 10)] | Les deux conditions doivent être vraies |
| Filtre OU | tab_resultat = tab_numpy[(tab_numpy < 0) | (tab_numpy > 10)] | Au moins une condition vraie |
| Remplacer selon condition | tab_resultat = np.where(tab_numpy < 0, 0, tab_numpy) | Si condition : met 0, sinon garde la valeur |
| Au moins un True | resultat = np.any(tab_numpy < 0) | True si au moins un élément satisfait |
| Tous True | resultat = np.all(tab_numpy > 0) | True si tous les éléments satisfont |
Les explications de cette section étaient-elles claires ?
En sciences, les données n’arrivent pas toujours dans le bon format. Des séries de mesures doivent parfois être regroupées, des jeux de données provenant de sources différentes doivent être combinés, et les résultats d’un calcul long doivent être conservés pour ne pas avoir à tout recalculer à chaque fois.
Cet onglet couvre les outils NumPy qui permettent de faire exactement ça : restructurer, combiner, générer et sauvegarder des tableaux.
reshape() - changer la forme sans changer les donnéesreshape() réorganise les éléments d’un tableau dans une nouvelle forme, sans modifier leur contenu. C’est utile quand un algorithme ou une bibliothèque attend des données dans un format précis : par exemple, un réseau de neurones qui attend une matrice plutôt qu’une liste à plat. Le nombre total d’éléments doit rester identique.
mesures = np.arange(12) # 12 mesures en une seule ligne
print(mesures) # [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(mesures.shape) # (12,)
grille = mesures.reshape(3, 4) # réorganiser en 3 séries de 4 mesures
print(grille)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(grille.shape) # (3, 4)
np.concatenate() - combiner des tableauxnp.concatenate() met plusieurs tableaux bout à bout pour en former un seul :
mesures_matin = np.array([36.5, 37.0, 36.8])
mesures_soir = np.array([37.2, 36.9, 37.5])
toutes_mesures = np.concatenate([mesures_matin, mesures_soir])
print(toutes_mesures) # [36.5 37. 36.8 37.2 36.9 37.5]
NumPy offre deux fonctions principales pour générer des données aléatoires :
np.random.uniform() génère des nombres décimaux aléatoires dans un intervalle [min, max[ :
# 5 mesures de température entre 36.0 (inclus) et 38.5 (exclus)
temperatures = np.random.uniform(36.0, 38.5, 5)
print(temperatures) # ex : [37.2 36.8 38.1 37.5 36.3]
np.random.randint() génère des nombres entiers aléatoires dans un intervalle [min, max[ :
# 10 valeurs de dés (entre 1 et 6 inclus)
des = np.random.randint(1, 7, 10)
print(des) # ex : [3 1 6 2 4 5 2 1 6 3]
Les fonctions aléatoires donnent un résultat différent chaque fois. Si l'on veut reproduire exactement le même résultat (pour déboguer ou tester), il faut utiliser np.random.seed(42) avant la génération. Le nombre entre parenthèses est arbitraire, c’est juste un point de départ fixe pour le générateur de nombres aléatoires.
np.save() permet de sauvegarder un tableau dans un fichier .npy, et np.load() de le recharger.
C’est utile pour conserver les résultats d’un calcul long et les réutiliser plus tard sans tout recalculer.
# Sauvegarder
scores = np.array([85, 92, 78, 90, 88])
np.save("scores.npy", scores)
# Charger dans un autre script (ou plus tard dans le même)
scores_charges = np.load("scores.npy")
print(scores_charges) # [85 92 78 90 88]
print(np.mean(scores_charges)) # 86.6
Le fichier scores.npy est créé dans le même dossier que le script.
.npy n’est pas lisible dans un éditeur de texteUn fichier .npy n'est pas un fichier texte, c'est un format binaire : les nombres sont stockés directement en mémoire, sans conversion en texte. Cela le rend beaucoup plus rapide à lire et à écrire qu’un fichier texte .txt, .csv ou .json, et plus compact sur le disque. En contrepartie, son contenu apparaîtra comme des caractères illisibles si on l’ouvre dans un éditeur. C’est tout à fait normal. Le fichier n’est pas corrompu. Il faut simplement le lire avec np.load().
Pour inspecter les données à la main ou les partager avec d’autres logiciels, mieux vaut utiliser un fichier texte .csv, .json ou .txt.
| Opération | Syntaxe | Description |
|---|---|---|
| Importer NumPy | import numpy as np | Convention universelle |
| Changer la forme | tab_resultat = tab_numpy.reshape(3, 4) | Réorganise en 3 lignes x 4 colonnes |
| Combiner des tableaux | tab_resultat = np.concatenate([tab_a, tab_b]) | Met tab_a et tab_b bout à bout |
| Entiers aléatoires | tab_resultat = np.random.randint(0, 10, 5) | 5 entiers aléatoires entre 0 et 9 |
| Décimaux aléatoires | tab_resultat = np.random.uniform(0, 1, 5) | 5 décimaux aléatoires entre 0 et 1 (1 exclus) |
| Sauvegarder | np.save('données.npy', tab_numpy) | Sauvegarde le tableau dans un fichier .npy |
| Charger | tab_numpy = np.load('données.npy') | Recharge le tableau depuis un fichier .npy |
Les explications de cette section étaient-elles claires ?
Matplotlib s’intègre naturellement avec NumPy : on génère les données avec NumPy (tableaux de valeurs x et y), puis on les transmet directement à Matplotlib pour tracer le graphique. Ensemble, ils permettent de visualiser n’importe quelle fonction mathématique ou jeu de données en quelques lignes.
linspace() → fonction → plot()Le pattern de base est toujours le même :
- Créer un tableau de valeurs
xavecnp.linspace() - Calculer les valeurs
ycorrespondantes avec une opération vectorisée - Tracer le graphique avec
plt.plot(x, y)
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 100) # 100 points entre 0 et 10
y = np.sin(x) # calcul vectorisé : sin() sur chaque point
plt.plot(x, y)
plt.title("Fonction sinus")
plt.xlabel("x")
plt.ylabel("sin(x)")
plt.grid()
plt.show()

Les trois exemples qui suivent illustrent les cas les plus courants : tracer une fonction algébrique, superposer plusieurs courbes sur le même graphique, et tracer une courbe paramétrique. Dans chaque cas, NumPy génère les tableaux x et y, et Matplotlib s'occupe de l'affichage.
Grâce à la vectorisation, on peut exprimer la formule directement sur le tableau x :
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-10, 100, 1000)
y = 2 * x - 15 # opération vectorisée : appliquée à chaque élément de x
plt.plot(x, y)
plt.title("Fonction linéaire : y = 2x - 15")
plt.xlabel("x")
plt.ylabel("y")
plt.grid()
plt.show()

On peut tracer plusieurs courbes sur le même graphique en appelant plt.plot() plusieurs fois :
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(-5, 5, 200)
plt.plot(x, np.sin(x), label="sin(x)")
plt.plot(x, np.cos(x), label="cos(x)")
plt.plot(x, np.sin(2*x), label="sin(2x)")
plt.title("Fonctions trigonométriques")
plt.xlabel("x")
plt.ylabel("y")
plt.legend()
plt.grid()
plt.show()

Un cercle n’est pas le graphique d’une fonction de la forme , car une même valeur de peut correspondre à deux valeurs de .
On peut toutefois le tracer avec des tableaux de coordonnées paramétriques (cos(θ), sin(θ)) :
import numpy as np
import matplotlib.pyplot as plt
angles = np.linspace(0, 2 * np.pi, 100) # 100 angles de 0 à 2π
x = np.cos(angles)
y = np.sin(angles)
plt.plot(x, y)
plt.axis("equal") # force la même échelle sur les deux axes
plt.title("Cercle unité")
plt.grid()
plt.show()

plt.axis("equal") est essentiel ici : sans cette ligne, Matplotlib peut utiliser une échelle différente sur les deux axes, ce qui fait apparaître le cercle comme une ellipse. En forçant la même échelle sur x et y, on garantit que le cercle apparaît bien rond.
| Opération | Syntaxe | Description |
|---|---|---|
| Importer NumPy | import numpy as np | Convention universelle |
| Importer Matplotlib | import matplotlib.pyplot as plt | Convention universelle |
| Générer des x | x = np.linspace(0, 10, 100) | 100 points entre 0 et 10 |
| Fonction mathématique | y = np.sin(x) | Calcule y pour chaque x |
| Fonction algébrique | y = 2 * x + 3 | Opérateurs vectorisés pour y = 2x + 3 |
| Axes à la même échelle | plt.axis("equal") | Même échelle sur x et y (cercle bien rond, pas une ellipse) |
Les explications de cette section étaient-elles claires ?
Pour favoriser une progression efficace, ce cours adopte une approche de classe inversée. Ce modèle déplace l'acquisition théorique hors de la classe pour transformer les heures de rencontre en véritables séances d'application pratique.
-
À la maison (Exploration et Appropriation) : Vous êtes le maître de votre rythme. Ces activités vous permettent de découvrir les nouveaux concepts et tester les exemples au moment où vous êtes le plus concentré. Si une notion vous semble obscure, n'hésitez pas à poser des questions à votre prof au fur et à mesure.
-
En classe (Application et Consolidation) : Le temps en présentiel est une ressource précieuse. Nous l'utilisons pour nous attaquer aux défis plus complexes et aux exercices de programmation qui demandent une mobilisation active de vos connaissances. C’est le moment idéal pour obtenir une rétroaction immédiate, collaborer avec vos pairs et bénéficier de l'accompagnement de votre enseignant au moment où vous en avez le plus besoin.
- 🏠 Activités à faire à la maison
- 🏫 Activités à faire en classe
🧠 Auto-validation des connaissances
Ce formulaire sert à vérifier votre compréhension des éléments les plus importants de la rencontre R10. Ne faites ce questionnaire que lorsque vous vous sentez en très bonne maîtrise de la matière. En classe, dès votre arrivée, vous aurez un questionnaire très similaire, évalué sommativement, à compléter sans accès à aucune documentation.
Ne pas remplir le formulaire diminue fortement vos chances de réussir l’évaluation sommative en début de rencontre.
Assurez-vous de bien comprendre toutes les notions derrière chaque question.
🔨 Exercices de création
Pour chacun des exercices de cette section, vous devez créer des fichiers .py avec les noms indiqués.
Pour les exercices de cette section, vous pouvez consulter librement la documentation du site web du cours.
📁 Créez un fichier r10_creer_inspecter_tableaux_numpy.py pour votre réponse.
Un technicien en laboratoire prépare des séries de mesures. Créez les tableaux suivants dans l'ordre ci-dessous, et affichez les valeurs, le shape et le dtype de chacun. Ajoutez une ligne vide entre chaque tableau pour que l'affichage soit lisible.
- Un tableau de valeurs de pH mesurées :
[4.2, 6.8, 7.1, 5.5, 8.3] - Un tableau de 8 zéros représentant des températures initiales
- Un tableau de 5 uns représentant des facteurs de calibration
- Un tableau de 6 valeurs fixes à
9.81représentant la constante gravitationnelle - Un tableau de 6 positions espacées régulièrement entre 0 et 50 mètres
- Un tableau des entiers de 0 à 20 par pas de 2
Pour chaque tableau, l'affichage doit suivre ce format, séparé par une ligne vide :
valeurs : [4.2 6.8 7.1 5.5 8.3]
shape : (5,)
dtype : float64
valeurs : [0. 0. 0. 0. 0. 0. 0. 0.]
shape : (8,)
dtype : float64
valeurs : [1. 1. 1. 1. 1.]
shape : (5,)
dtype : float64
valeurs : [9.81 9.81 9.81 9.81 9.81 9.81]
shape : (6,)
dtype : float64
valeurs : [ 0. 10. 20. 30. 40. 50.]
shape : (6,)
dtype : float64
valeurs : [ 0 2 4 6 8 10 12 14 16 18 20]
shape : (11,)
dtype : int64
💡 Créer une fonction pour l'affichage d'un tableau vous ferait sauver beaucoup de lignes de code!
Création de tableaux NumPy, shape, dtype
📁 Créez un fichier r10_numpy_vs_boucles.py pour votre réponse.
Un physicien calcule la vitesse finale de 10 000 000 objets à l'aide de la formule
où :
- m/s est la vitesse initiale (la même pour tous les objets)
- est l'accélération propre à chaque objet (chargée depuis un fichier)
- s est le temps écoulé (le même pour tous les objets)
Par exemple, pour le premier objet ( m/s²) :
Téléchargez le fichier accelerations.npy et placez-le dans le même répertoire que votre script.
accelerations.npyCe fichier pèse ~70 Mo et ne doit pas être ajouté à GitHub.
Ajoutez-le à votre .gitignore :
accelerations.npy
ou encore, pour carrément exclure tous les fichiers se terminant par .npy :
*.npy
Utilisez le code suivant pour charger les données sous deux formes :
import numpy as np
import time
accelerations_np = np.load("accelerations.npy") # tableau NumPy
accelerations_list = list(accelerations_np) # liste Python
Calcul des vitesses
- Calculez les vitesses finales avec une boucle Python (à partir de
accelerations_list) et mesurez le temps d'exécution avectime.time(). - Calculez les vitesses finales avec NumPy (sans boucle, à partir de
accelerations_np) et mesurez le temps d'exécution. - Avec NumPy, calculez :
- la vitesse finale minimale, maximale et moyenne parmi les 10 millions d'objets.
- les 3 premières accélérations et les 3 premières vitesses finales calculées.
- l'indice de la vitesse finale la plus élevée.
- Affichez les résultats en respectant le format suivant :
Temps d'exécution
- Solution avec boucle : 1.35896015 secondes
- Solution avec NumPy : 0.14341521 secondes
Statistiques sur les vitesses finales
- minimum : 6.5
- maximum : 35.0
- moyenne : 20.74975367
Détails
- Les 3 premières accélérations : [4.1 9.5 7.5]
- Les 3 premières vitesses finales calculées : [17.3 33.5 27.5]
- Indice de la vitesse finale la plus élevée : 531
Opérateurs arithmétiques vectorisés, NumPy vs boucles Python, fonctions d'agrégation
📁 Créez un fichier r10_oscillation_amortie.py pour votre réponse.
Un ingénieur simule le déplacement vertical d'une bille sur un ressort selon la formule d'une oscillation amortie :
Les paramètres de la simulation sont les suivants :
A = 5 # amplitude
omega = 2 * np.pi # fréquence angulaire (le ω)
alpha = 0.3 # coefficient d'amortissement (le α)
Préparation des données
- Créez un tableau
tde 200 valeurs de temps entre 0 et 4 secondes. - Calculez le tableau des positions
yà partir de la formule ci-dessus :
Analyse des résultats
- Affichez la position maximale atteinte et la position minimale (en mètres).
- Affichez à quel indice la bille est au plus haut, ainsi que l'instant correspondant (en secondes).
Visualisation
- Tracez un graphique du déplacement
yen fonction du temps, avec un titre, des étiquettes d'axes et une grille.
Résultat attendu à la console :
Position maximale : 4.6438734623073290 m
Position minimale : -3.9969968857329263 m
Indice au plus haut : 12
Instant correspondant : 0.2412060301507538 s
Résultat attendu du graphique :

Fonctions mathématiques vectorisées, fonctions d'agrégation, opérateurs arithmétiques
📁 Créez un fichier r10_notes_etudiants.py pour votre réponse.
Un enseignant dispose des notes de 10 étudiants (sur 100 points) :
resultats = np.array([45, 72, 38, 91, 60, 55, 83, 29, 74, 66])
À chaque étape, réalisez l'action demandée puis affichez le résultat.
Filtrage
- Créez un masque booléen identifiant les étudiants en échec (note inférieure à 60).
- Créez un tableau
notes_echeccontenant uniquement les notes des étudiants en échec. - Affichez le nombre d'étudiants en échec.
Transformation
- Créez un tableau
mentionsqui attribue automatiquement une mention à chaque étudiant :"réussite"si la note est ≥ 60,"échec"sinon.
Analyse
- Calculez la note moyenne, affichez-la, puis affichez combien d'étudiants sont au-dessus de la moyenne.
Résultat attendu :
Masque échec : [ True False True False False True False True False False]
Notes en échec : [45 38 55 29]
Nombre en échec : 4
Mentions : ['échec' 'réussite' 'échec' 'réussite' 'réussite' 'échec' 'réussite' 'échec' 'réussite' 'réussite']
Moyenne : 61.3
Étudiants au-dessus de la moyenne : 5
Masques booléens, filtrage direct, transformation conditionnelle, fonctions d'agrégation
📁 Créez un fichier r10_traitement_pixels.py pour votre réponse.
Un système de traitement d'images reçoit des valeurs de pixels brutes qui peuvent dépasser les limites valides [0, 255]. Le pipeline de traitement se déroule en trois phases : d'abord détecter et corriger les valeurs invalides, puis normaliser les pixels entre 0 et 1, et enfin binariser l'image en noir et blanc.
pixels = np.array([-30, 0, 85, 128, 260, 300, 72, -5, 200, 255])
À chaque étape, réalisez l'action demandée puis affichez le résultat.
Détection et correction
- Calculez un masque booléen indiquant quelles valeurs sont hors limites (inférieures à 0 ou supérieures à 255).
- Vérifiez s'il existe au moins une valeur hors limites.
- Corrigez les pixels en forçant toute valeur inférieure à
0à0et toute valeur supérieure à255à255. - Vérifiez que toutes les valeurs sont maintenant valides.
Transformation
- Ramenez les pixels dans l'intervalle
[0.0, 1.0]en divisant chaque valeur par 255 (0 reste 0, 255 devient 1.0). - Convertissez chaque pixel en noir ou blanc : les valeurs inférieures à
0.5deviennent0.0(noir) et les autres deviennent1.0(blanc).
Résultat attendu :
Masque hors limites : [ True False False False True True False True False False]
Au moins une hors limite : True
Pixels corrigés : [ 0 0 85 128 255 255 72 0 200 255]
Toutes les valeurs valides : True
Pixels normalisés : [0. 0. 0.3333 0.502 1. 1. 0.2824 0. 0.7843 1. ]
Pixels binarisés : [0. 0. 0. 1. 1. 1. 0. 0. 1. 1.]
Masques booléens, filtrage direct, vérification de conditions globales, encadrement de valeurs, opérateurs arithmétiques, transformation conditionnelle
📁 Créez un fichier r10_manipulation_aleatoire.py pour votre réponse.
Un chercheur simule deux séries de mesures de pression atmosphérique (en hPa) et veut les combiner, les analyser et les sauvegarder.
À chaque étape, réalisez l'action demandée puis affichez le résultat.
Génération
- Générez une première série de 6 mesures décimales aléatoires entre 990 et 1010 à l'aide de NumPy (sans utiliser le module
randomde Python). - Générez une deuxième série de 6 mesures entières aléatoires entre 995 et 1005 à l'aide de NumPy.
Manipulation
- Combinez les deux séries en un seul tableau de 12 valeurs et affichez-le.
- Remplacez toutes les valeurs inférieures à 1000 par
1000.0et affichez le résultat. - Restructurez le tableau en une matrice de 3 lignes × 4 colonnes et affichez-la avec son
shape.
Les valeurs seront différentes à chaque exécution puisqu'elles sont aléatoires, mais le format doit être identique. Exemple :
Tableau combiné : [ 997.49 1009.01 1004.64 1001.97 993.12 993.12 1005. 1005. 1002. 999. 998. 1002.]
Valeurs corrigées : [1000. 1009.01 1004.64 1001.97 1000. 1000. 1005. 1005. 1002. 1000. 1000. 1002.]
Matrice (3, 4) :
[[1000. 1009.01 1004.64 1001.97]
[1000. 1000. 1005. 1005. ]
[1002. 1000. 1000. 1002. ]]
Génération aléatoire, combinaison de tableaux, encadrement de valeurs, restructuration
📁 Créez un fichier r10_fichiers_json.py pour votre réponse.
Un étudiant en sciences veut sauvegarder les résultats d'une expérience de laboratoire dans un fichier JSON, puis les relire pour les afficher.
Voici les données de l'expérience :
- Nom de l'expérience :
"Réaction acide-base" - Température ambiante :
22.5 - Réaction observée :
True - Mesures de pH relevées :
[4.2, 5.1, 6.7, 7.0, 6.3]
Sauvegarde
- Créez un dictionnaire Python contenant ces données.
- Sauvegardez ce dictionnaire dans un fichier
experience.jsonavec une indentation de 4.
Le fichier experience.json généré doit ressembler à :
{
"nom": "Réaction acide-base",
"temperature": 22.5,
"reaction_observee": true,
"mesures_ph": [
4.2,
5.1,
6.7,
7.0,
6.3
]
}
Lecture et affichage
- Relisez le fichier
experience.jsonet stockez son contenu dans une variable. - Affichez le nom de l'expérience, la température ambiante et la moyenne des mesures de pH.
Le résultat attendu est :
Expérience : Réaction acide-base
Température : 22.5 °C
pH moyen : 5.86
📁 Créez un fichier r10_fichiers_texte.py pour votre réponse.
Un système de capteurs enregistre des mesures de température au fil du temps. Simulez ce système en trois étapes.
Étape 1 - Créer le fichier (mode "w")
Générez 5 nombres entiers aléatoires entre -10 et 35 à l'aide de NumPy (sans utiliser le module random de Python) et
écrivez-les dans un fichier temperatures.txt, un nombre par ligne.
Étape 2 - Ajouter des mesures (mode "a")
Générez 3 nouveaux nombres entiers aléatoires entre -10 et 35 à l'aide de NumPy et
ajoutez-les à la suite du fichier temperatures.txt, sans effacer les données existantes.
Étape 3 - Lire et analyser (mode "r")
- Lisez toutes les lignes du fichier.
- Retirez les sauts de ligne de chaque valeur.
- Convertissez chaque valeur en entier.
- Créez un tableau NumPy à partir des valeurs lues.
- Affichez la liste complète des 8 températures.
- Affichez la somme des températures à l'aide de NumPy.
- Affichez la température maximale à l'aide de NumPy.
- Affichez la température minimale à l'aide de NumPy.
Les valeurs seront différentes à chaque exécution puisqu'elles sont aléatoires, mais le format doit être identique :
Températures enregistrées : [ 3 17 -5 22 8 11 -2 30]
Somme : 84
Maximum : 30
Minimum : -5
✏️ Exercices sur papier
Les exercices suivants ne visent pas nécessairement à pratiquer la matière de cette rencontre,
mais plutôt à vous entraîner à l'écriture de code "papier" sur des concepts plus simples, comme il pourrait y avoir à l'examen.
Faites ces exercices d'abord sur papier (ou dans un éditeur de texte simple) et sans aucune documentation, comme à l'examen.
Vous pouvez valider votre réponse dans PyCharm à la fin — un luxe que vous n'aurez pas le jour de l'examen, d'où l'importance de vous entraîner sans lui.
Sur papier, sans ordinateur, écrivez du code permettant de connaitre le nombre de valeurs supérieures à 50 dans une liste.
Prenez la liste suivante comme référence :
liste = [20, 60, 50, 10, 70, 90]
Avec ce contenu de liste, le programme devrait afficher le résultat suivant :
3
Votre programme doit fonctionner peu importe le nombre d'éléments dans la liste et quels que soient ces nombres.
📁 Créez un fichier r10_sans_pycharm_1.py pour valider votre réponse à l'aide de PyCharm.
Sur papier, sans ordinateur, écrivez du code permettant de résoudre le problème ci-dessous.
On dispose d'une liste nommée liste contenant des tuples. Chaque tuple est composé d'une lettre et d'un nombre.
On dispose également d'une variable lettre qui contient le caractère à rechercher.
liste = [("a", 1), ("b", 2), ("a", 3), ("c", 4), ("b", 5)]
lettre = "a"
L'objectif est d'afficher la somme des deuxième éléments de chaque tuple, mais uniquement lorsque le premier élément du tuple correspond à la valeur stockée dans la variable lettre.
Résultats attendus
Voici les résultats attendues selons différentes lettres :
- si
lettre = "a"➡️ votre programme doit afficher :4 - si
lettre = "b"➡️ votre programme doit afficher :7 - si
lettre = "c"➡️ votre programme doit afficher :4 - si
lettre = "d"➡️ votre programme doit afficher :0
Votre programme doit fonctionner correctement quelles que soient les valeurs contenues dans liste et dans lettre.
📁 Créez un fichier r10_sans_pycharm_2.py pour valider votre réponse à l'aide de PyCharm.
Sur papier, sans ordinateur, tracez le graphique correspondant au code suivant le plus fidèlement possible. Graduez vos axes.
import matplotlib.pyplot as plt
x = [0, 1, 2, 3, 4, 5]
y = [0, 1, 4, 9, 16, 25]
plt.plot(x, y, marker='o', label='y = x^2')
plt.title("Graphique de la fonction y = x^2")
plt.xlabel("x")
plt.ylabel("y")
plt.grid()
plt.legend()
plt.show()
Une fois votre graphique tracé sur papier, validez votre réponse à l'aide de Pycharm.
Sur papier, sans ordinateur, tracez le graphique correspondant au code suivant le plus fidèlement possible. Graduez vos axes.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-10, 10, 100)
y = x ** 2
plt.plot(x, y, label='y = x^2')
plt.title("Graphique de la fonction y = x^2")
plt.xlabel("x")
plt.ylabel("y")
plt.grid()
plt.legend()
plt.show()
💡 La courbe n'a pas besoin d'être parfaite, mais elle doit passer par des points clés.
Une fois votre graphique tracé sur papier, validez votre réponse à l'aide de Pycharm.
🎯 Solutions des exercices
Un solutionnaire possible pour chaque exercice est disponible en format vidéo avec des explications. Vous pouvez vous en servir pour comparer votre solution avec une solution possible jugée optimale et vous débloquer après un long moment bloqué sur un exercice (ex. 20 minutes) et après avoir utilisé le débogueur pour essayer par vous-même de trouver le problème.
Il est tout à fait normal que certains problèmes demandent du temps, de la réflexion, et parfois même un peu de frustration. C’est précisément dans ces moments d’effort que l’apprentissage s’ancre réellement.
Consulter un solutionnaire avant d’avoir tenté l’exercice par soi-même, ou le parcourir trop rapidement, revient à court-circuiter le processus d’apprentissage. Ce n’est pas simplement contre-productif, c’est pédagogiquement désastreux.
En sautant l’étape de la réflexion personnelle, on prive son cerveau de l’occasion de construire des connexions durables. Et à force de répéter ce réflexe, on risque de passer à côté des compétences essentielles, ce qui peut mener à des échecs plus tard, même si tout semble facile sur le moment. Alors oui, prenez le temps. L’erreur fait partie du jeu. C’est en cherchant, en tâtonnant, en doutant, qu’on devient réellement compétent. Le solutionnaire doit être un outil de validation, pas un raccourci.
🔨 Solution des exercices de création :
- Créer et inspecter des tableaux
- NumPy vs boucles
- Oscillation amortie
- Notes d'étudiants
- Traitement des pixels
- Manipulation et aléatoire
- Fichier JSON
- Fichiers texte
✏️ Solution des exercices sur papier :