Simulation Numeric
Simulation Numeric
Simulation numérique
Classes Préparatoires aux Ecoles d’Ingénieur (CPEI)
MP & PC : Semestre 4
Volume horaire : 18 H
Cours Théorique: 12 H, TD/TP: 06 H
Cours de :
Cheick Amed Diloma Gabriel T RAORÉ
[Link]@[Link]
Sommaire
i
ii
II Calcul numérique 70
9 Calcul numérique approché 71
9.1 Erreurs absolue et relative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
9.1.1 Erreur absolue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
9.1.2 Erreur relative . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
9.2 Incertitudes absolue et relative . . . . . . . . . . . . . . . . . . . . . . . . . . 72
9.3 Représentation décimale d’un nombre approché . . . . . . . . . . . . . . . . . 72
iii
Bibliographie 101
Introduction et installation de l'environnement de
simulation
La simulation numérique, ou plus largement le calcul numérique, est un domaine des mathé-
matiques appliquées qui se concentre sur l’utilisation d’algorithmes et de méthodes numériques
pour résoudre des problèmes mathématiques difficilement résolubles à la main. Ces problèmes,
souvent impossibles ou très difficiles à résoudre analytiquement, impliquent généralement des
équations différentielles, des intégrales ou des systèmes d’équations non linéaires. Le calcul nu-
mérique repose sur des approximations et des simulations permettant de fournir des solutions
pratiques, même si elles ne sont pas exactes.
Pourquoi l'enseigner ?
Le calcul numérique est une passerelle entre la théorie mathématique et le monde réel. L’en-
seigner permet de doter les étudiants d’outils et de compétences nécessaires pour relever les
défis scientifiques et technologiques modernes. Ci-dessous nous énumérons quelques raisons
d’enseigner les simulations numériques.
Applications interdisciplinaires
Le calcul numérique est essentiel dans diverses disciplines, notamment la physique, la chimie, la
biologie, l’économie, la finance, la sociologie et l’intelligence artificielle. Il permet de modéliser
des phénomènes naturels, de prévoir des comportements ou d’optimiser des systèmes.
1
2
À propos de ce cours
Ce cours est destiné aux étudiants de 2ème année des classes préparatoires de l’École Poly-
technique de Ouagadougou (EPO). Son objectif principal est de fournir une variété d’outils
numériques permettant de résoudre efficacement un large éventail de problèmes scientifiques.
Grâce à une approche pédagogique combinant Cours Magistraux (CM), Travaux Dirigés (TD)
et Travaux Pratiques (TP), les étudiants développeront des compétences pratiques et théoriques
adaptées aux défis scientifiques modernes.
Pour rendre l’apprentissage concret et accessible, chaque chapitre du cours sera accompagné
d’exemples illustratifs et d’une série d’exercices. Ces activités renforceront leur compréhension
et faciliteront l’application des techniques enseignées.
Prérequis
Une bonne maîtrise des concepts fondamentaux suivants est indispensable : équations différen-
tielles, méthodes d’intégration, algèbre linéaire.
Objectifs pédagogiques
Au terme du cours, l’apprenant devra être capable de :
• développer une expertise dans l’utilisation de bibliothèques Python spécialisées, notam-
ment numpy, scipy, matplotlib et pandas ;
• acquérir des compétences pratiques pour résoudre des problèmes scientifiques complexes
grâce aux techniques de simulation numérique ;
• maîtriser la visualisation et l’analyse des données à l’aide d’outils graphiques.
3
Évaluation
Le cours sera évalué à travers un devoir sur table et un TP, permettant de valider les acquis
théoriques et pratiques.
Cela signifie que vous devez installer Python (version 3.12 ou supérieure) sur votre ordinateur
et installer une application Jupyter Notebooks 1 .
Pour travailler sur les tâches de programmation, vous devez installer les paquets Python sui-
vants : numpy, scipy, seaborn, pandas et matplotlib. Ceux qui souhaite se familiariser avec jupy-
ter notebook peuvent suivre la vidéo : [Link]
Remarque 0.1 (Aide : installer jupyter notebook en ligne de commande). Pour installer jupyter
notebook en ligne de commande, vous pouvez suivre les instruction suivante :
1. Ouvrez l’invite de commandes : appuyez sur la touche Windows, tapez « cmd » et appuyez
sur Entrée.
2. Installez Jupyter Notebook : dans l’invite de commandes, tapez la commande suivante et
appuyez sur Entrée : pip install jupyter notebook
3. Lancez Jupyter Notebook : une fois l’installation terminée, tapez la commande suivante
et appuyez sur Entrée : jupyter notebook
Jupyter Notebook s’ouvrira dans votre navigateur web par défaut. Si vous avez un mes-
sage d’erreur (peut-être parce que vous avez anaconda sur votre machine), utilisez la
commande : python -m notebook
Un des atouts majeurs du notebook réside dans sa capacité à combiner code et texte. En ef-
fet, il permet non seulement de programmer, mais aussi de rédiger du texte enrichi grâce au
langage de formatage Markdown. Voici ci-dessous quelques exemples d’instructions en Mark-
down.
Aide-mémoire Markdown
Un titre de niveau 1 :
# Titre
Un titre de niveau 2 :
## Subtitle
Un titre de niveau 3 :
### Sous-soustitre
Texte en gras:
**bold text**
Texte en italique:
*italic text*
Tâches
Les travaux pratiques sont destinés à compléter les cours magistraux et à vous faire appliquer la
théorie que vous avez apprise dans les cours magistraux.
Les exercices seront résolus à la fois avec du papier-crayon (pour la formulation mathématiques
et les preuves analytiques) et de la programmation (pour la simulation).
Conclusion
Nous espérons que ce programme vous enthousiasmera et vous donnera les outils nécessaires
pour aborder les défis scientifiques de manière innovante et efficace !
Première partie
5
6
Bonjour et bienvenue dans cette partie consacrée aux librairies Python pour la Data Science,
plus précisément pour le calcul numérique.
Dans cette partie, vous allez découvrir les bonnes pratiques et les connaissances fondamen-
tales qui vous aideront à effectuer vos analyses de données ou calculs scientifiques à l’aide de
librairies Python. Vous verrez comment utiliser des librairies Python comme NumPy, Pandas,
Matplotlib ou encore Seaborn pour explorer vos données et les analyser. D’autre part pour
sauvegarder ou présenter vos résultats( sous forme de graphiques). À l’issue de cette partie, vous
saurez :
• manipuler des tableaux avec NumPy ;
• créer des data frames avec Pandas ;
• construire des data visualisations avec Matplotlib et Seaborn.
Python possède de nombreuses librairies, utilisées dans tous les domaines. Pour pouvoir traiter
une grande quantité de données, il est essentiel d’observer quelques règles de base, que vous
allez découvrir dans ce cours.
Dans la première partie, vous prendrez en main NumPy à travers la création d’arrays et de
tableaux de données.
Ensuite, dans la seconde partie du cours, vous créerez vos premiers data frames grâce à Pandas,
et vous les manipulerez grâce à différentes fonctions.
Pour finir, dans le dernier chapitre, vous construirez des data visualisations grâce aux librairies
Matplotlib et Seaborn.
Pour ce faire, vous pourrez pratiquer dans des notebooks créés pour l’occasion. Afin de
trouver les solutions justes, je vous recommande :
1. raisonner sur des feuilles de papier ;
2. résoudre mathématiquement les exercices sur vos feuilles ;
3. traduire vous solutions en algorithmes ;
4. simuler vos algorithmes c’est-à-dire traduire vos algorithmes en Python.
Dans cette première partie du cours, nous nous appuierons sur des fondations solides, largement
inspirées par les éclairages pertinents et la structure pédagogique du remarquable travail de
Benjamin Marlé et Nicolas Rangeon pour [Link]. Leur approche constitue une
base précieuse pour appréhender ces concepts initiaux.
Manipulez des tableaux avec NumPy
1
Les Data Analysts, les Data Scientists ou Mathématiciens ont au quotidien à manipuler des
données en grande quantité et de sources très variées. Celles-ci sont généralement représentées
sous la forme de listes ou tableaux de nombres. Cependant, les objets natifs de Python sont assez
limités pour les manipuler correctement.
Considérons par exemple la liste suivante, représentant le revenu mensuel de cinq clients de
notre banque :
Si on souhaite calculer la moyenne des éléments de cette liste, il n’y a pas de fonction Python
existante par défaut permettant de le faire : il faudrait la recoder soi-même ! C’est encore plus
compliqué si on souhaite avoir une information plus spécifique, comme la médiane. C’est là que
la librairie NumPy intervient !
Diminutif de Numerical Python, Numpy elle fournit un ensemble de fonctions pour effectuer
efficacement des opérations sur les données, mais propose également un objet qui est au cœur
de presque tout l’écosystème data en Python : l’array.
Découvrons un peu plus en détail cette librairie, et pourquoi elle est aussi réputée dans l’envi-
ronnement data Python aujourd’hui !
Remarque 1.1. Si Numpy n’est pas installé dans votre ordinateur, vous pouvez l’intaller en
ligne de commande via l’instruction : pip install numpy .
7
1.1. DIFFÉRENCIEZ LES ARRAYS DES LISTES CLASSIQUES 8
Reprenons notre exemple de calcul de la moyenne présenté ci-dessus. Dans les faits, la fonction
n’est pas très complexe. Elle pourrait s’écrire :
def moyenne(liste):
return sum(liste)/len(liste)
OK ça a l’air bien ... mais je ne vois pas non plus la révolution annoncée ?
C’est tout à fait logique, car la vraie révolution vient avec les arrays NumPy ! On estime qu’à
mesure que la taille du tableau augmente, des opérations via array NumPy deviennent environ
30 fois plus rapides que via une liste Python classique.
Cette différence aussi importante s’explique par le fait que les arrays NumPy ne peuvent contenir
qu’un seul et même type. En effet, contrairement à une liste classique où l’on peut stocker tous
types d’objets, NumPy n’acceptera qu’un seul type en entrée.
De plus, NumPy donne également accès à de nombreuses autres fonctions mathématiques indis-
pensables, applicables à des arrays ou même à des listes :
Il existe encore de nombreuses autres fonctions, que je vous invite à découvrir dans la documen-
tation de NumPy. A présent, allons créer notre premier array.
0. Le lien est : [Link]
1.1. DIFFÉRENCIEZ LES ARRAYS DES LISTES CLASSIQUES 9
Pour plus d’informations sur les types NumPy, consultez la page Data types de la documen-
tation officielle.
[Link]
Il existe également des fonctions NumPy permettant de créer des arrays selon un certain pattern
ou une spécification particulière. Les plus couramment utilisées sont :
[Link](n) : permet de créer un array de n éléments contenant que des 0 ;
[Link](n) : permet de créer un array de n éléments contenant que des 1 ;
[Link](i, j, p) : permet de créer un array rempli avec une séquence linéaire, qui ira de i à j,
par pas de p ;
[Link](i, j, n) : permet de créer un array de n valeurs espacées uniformément entre i et j.
Voyons à présent comment sélectionner des éléments au sein d’un array NumPy.
1.2. SÉLECTIONNEZ DES ÉLÉMENTS AU SEIN D’UN ARRAY 10
Remarque 1.3. Lors d’un slicing, le début peut être omis si on veut commencer au début de la
liste (c’est-à-dire si début = 0). La fin peut être omise si on veut aller jusqu’au bout de la liste
(c’est-à-dire fin = -1 ou fin = len(liste)). Le pas, ainsi que le dernier :, peuvent être
omis si le pas est de 1 (-1 si la fin est inférieure au début).
Slicing
print(revenus_array[:3]) # Les 3 premiers éléments (de l'indice 0 à 2)
Si le pas est négatif, le début et la fin du slice sont inversés. On peut utiliser cette propriété
1.2. SÉLECTIONNEZ DES ÉLÉMENTS AU SEIN D’UN ARRAY 11
En effet, de la même façon qu’il est possible de sélectionner des éléments via leur indice, il est
possible avec les arrays NumPy de renseigner la condition selon laquelle on souhaite sélection-
ner les éléments du tableau, avec l’écriture nom_array[condition de sélection].
Voilà par exemple comment sélectionner uniquement les valeurs supérieures à 2 000 :
Sélection conditionnelle d’éléments d’un array
revenus_array[revenus_array > 2000]
# array([2200, 3000, 2172])
Remarque 1.4. On pourrait naïvement exécuter revenus_array[ > 2000] en pensant que
Python comprendra qu’on souhaite appliquer la condition à l’array qui est cité juste avant. Le
résultat sera une erreur. Il faut bien considérer que l’array dans lequel on sélectionne, et la
condition à appliquer, sont deux choses différentes. Même si cela concerne le même array, il est
nécessaire de le spécifier également dans la condition !
Le et logique (respectivement ou logique) n’est pas matérialisé par le mot clé and (respec-
tivement or) comme dans une structure conditionnelle if classique, mais par le symbole
& (respectivement |). De plus, chaque condition doit être absolument délimitée par des pa-
renthèses, sous peine de rencontrer une erreur. Cette écriture s’explique par le fait qu’on ne
1.3. UTILISEZ LES MÉTHODES D’ARRAY 12
compare pas des booléens, mais des arrays de booléens, terme à terme.
Le résultat nous indique qu’on a un array contenant 5 éléments (nous verrons ultérieurement
la raison de la virgule après le 5).
Aux arrays, on peut également appliquer de nombreuses opérations mathématiques grâce à des
fonctions intégrées (dont certaines sont programmées par des scientifiques comme vous et moi).
# calculer la somme :
revenus_array.sum()
Cette liste est naturellement non exhaustive ! Vous pouvez trouver la liste de l’ensemble des
méthodes applicables à un array directement dans la documentation officielle.
Exercice d’application 1.1 (Consignes). Pour cette première tâche, nous avons à notre disposi-
tion les revenus de 10 clients de notre banque. Vous aurez à utiliser les différentes manipulations
présentées dans ce chapitre pour sélectionner certains revenus selon une condition spécifique,
et effectuer diverses opérations.
Je vous invite à lire le notebook préparé à cet effet et a compléter les portions de code dans les
cellules correspondantes. Ce notebook est disponible au lien : https: // colab. research.
google. com/ drive/ 1R2-Yjt-yGiSb5QL9BTjK6eH8kAAAGyJ2? usp= sharing
Transformez vos données en tableaux
2
2.1 Créez un tableau avec NumPy
Jusque-là, nous n’avons vu que des tableaux/arrays à une dimension, mais on ne travaille que
très rarement avec une seule colonne 1 .
Prenons un exemple : vous travaillez dans le milieu bancaire et vous avez besoin de créer un
tableau où vous retrouveriez, en plus des revenus de vos clients, leurs mensualités de rembour-
sement de prêt, le nombre d’enfants à charge, et toute autre information susceptible de vous être
utile. Considérons les clients suivants :
• Hugo, un jeune homme de 21 ans, gagnant 1 400 par mois et n’ayant aucun enfant ;
• Richard, un homme de 54 ans, gagnant 2800 par mois et ayant 2 enfants ;
• Émilie, une femme de 27 ans gagnant 3 700 et ayant 3 enfants.
Nos données peuvent être représentées via ce tableau :
Nom Âge Revenus Nombre d’enfants
Hugo 21 1400 0
Richard 54 2800 2
Émilie 27 3700 3
Et voici comment pourrait se matérialiser ce tableau en Python, en utilisant des listes :
1. Notons que la dimension d’un tableau réfère principalement au nombre de colonnes du tableau. En effet, les
variables que nous étudions ou créons au besoin sont principalement stockées dans les colonnes des tableaux.
14
2.1. CRÉEZ UN TABLEAU AVEC NUMPY 15
Vous vous en doutez très certainement, mais oui, encore une fois la réponse se trouve du côté
de NumPy et des arrays ! En effet, un array est un objet multidimensionnel, c’est-à-dire qu’il
est possible de créer des arrays de toutes dimensions, et que l’ensemble des méthodes d’array
prennent en compte ce côté multidimensionnel.
La façon la plus simple de créer un tableau est de le faire à partir d’une liste de listes Python,
comme avec une liste classique. Il suffira d’exécuter [Link](tableau) pour transformer
notre liste de listes en array NumPy de 3 lignes et 3 colonnes.
Voyons quelques autres exemples ensemble pour bien comprendre cette notion :
Remarque 2.1. Il est possible de créer des tableaux de plus de 2 dimensions. Par exemple, pour
un tableau en 3D il suffira d’utiliser une liste de listes de listes. Voyons quelques autres exemples
ensemble pour bien comprendre cette notion :
Dans NumPy, chaque dimension d’un tableau est appelée un axe. La matrice que vous avez
vue précédemment possède trois axes. Les tableaux à trois axes sont également appelés ta-
bleaux tridimensionnels (3D).
Pour accéder à un élément du tableau ci-dessus, vous devez fournir trois indices :
Exercice 2.1. Créer un tableau NumPy de dimension 3 contenant 2 ligne et 4 colonnes. Vous
pouvez remplir le tableau avec n’importe quel nombre.
Comme précédemment, nous pouvons également utiliser des fonctions NumPy pour créer des
tableaux plus ou moins complexes. Voici quelques exemples de fonctions couramment utilisées :
Reprenez ces fonctions et exécuter les dans votre propre environnement en changeant cer-
taines valeurs, pour bien appréhender leur fonctionnement.
Remarque 2.2. Les matrices sont une composante essentielle de l’algèbre linéaire. Vous al-
lez forcément être amené à croiser à nouveau leur chemin si vous poursuivez dans l’analyse
de données ou le calcul numérique, car elles sont la base même de nombreuses méthodes de
modélisation.
On peut également définir une matrice selon des conditions sur ces vecteurs.
Explication du code :
• Définition du nombre de points : num_points = 1 000 définit le nombre de points dans
chaque ligne du tableau. Ici, nous avons choisi 1 000 points.
• [Link](-100, 100, num_points) génère une séquence de num_points valeurs uni-
formément espacées entre −100 et 100. [[Link](-100, 150, num_points) pour i in
range(3)] crée une liste de trois lignes, chacune contenant num_points valeurs.
• [Link](...) convertit cette liste en un tableau NumPy.
• Affichage du tableau : print(D) affiche le tableau D afin qu’on vérifie si l’on a ce que
l’on veut.
En résumé, ce code crée un tableau NumPy de trois lignes, chaque ligne contenant 1 000
points uniformément espacés entre −100 et 150, puis affiche ce tableau.
2.2. ANALOGIE ENTRE LES ARRAYS ET LES MATRICES 18
display(E)
Explication du code :
1. Définition du pas : step = 0.5 définit le pas entre chaque point. Vous pouvez ajuster
cette valeur selon vos besoins.
2. Création du tableau avec un espacement spécifique :
• E = [Link]([[Link](-100, 100 + step, step) for i in range(3)])
crée un tableau NumPy.
• [Link](-100, 100 + step, step) génère une séquence de valeurs allant
de -100 à 100 (inclus) avec un espacement de step.
• [[Link](-100, 100 + step, step) for i in range(3)] crée une liste
de trois lignes, chacune contenant des valeurs espacées selon step.
• [Link](...) convertit cette liste en un tableau NumPy.
Remarque 2.3. En Numpy, les vecteurs des matrices sont des vecteurs lignes. Ainsi lors de la
définition de matrice, il faudra avoir en tête que, par défaut, les vecteurs sont ajoutés ligne après
ligne.
Une matrice aléatoire est une matrice dont les cellules contiennent des valeurs aléatoires. En
Numpy, une matrice aléatoire peut-être vue comme un vecteur de vecteur(s) aléatoire(s).
# matrice 4x4 avec des valeurs suivant une distribution binomiale (nombre
# de succès pour 10 essais avec une probabilité de succès de 0.5).
T = [Link](n=10, p=0.5, size=(4, 4))
La méthode .reshape() permet de modifier le format d’une matrice tout en conservant tous
les éléments de la matrice. Par exemple : [Link](1,4) .
Comme elles sont de même dimension (même nombre de lignes et de colonnes), on peut calculer
la somme (ou la différence) de la matrice A et de la matrice B, en additionnant terme à terme
chaque élément : " # " #
1 + 5 2 + 10 6 12
A+B = = .
3 + 15 4 + 20 18 24
2.2. ANALOGIE ENTRE LES ARRAYS ET LES MATRICES 20
Il est également possible de faire une multiplication terme à terme via l’opérateur *, comme
avec une multiplication normale : A*B, cela s’appelle la multiplication élément par élément.
Cependant, lorsqu’on effectue des calculs matriciels, on utilise beaucoup plus ce qu’on appelle
le produit matriciel. C’est un calcul assez fastidieux à faire à la main –d’autant plus avec des
matrices de grande dimension– mais qu’un ordinateur n’a en revanche aucun problème à réaliser.
Avec NumPy, le produit matriciel se fait via l’opérateur @ : A @ C. Cependant, cet opérateur
n’est disponible que depuis Python 3.5. Avant cela, le produit matriciel se faisait via la fonction
dot de NumPy : AC = [Link](A, C). Cette dernière fonctionne toujours aujourd’hui, les deux
syntaxes sont donc possibles !
Dans NumPy, il existe une bibliothèque dédiée à l’algèbre linéaire et à la résolution matricielle
de problèmes mathématiques. Cette sous-bibliothèque s’appelle [Link]. Pour l’impor-
ter, il suffit d’ajouter l’une des instructions suivante :
import [Link] as linalg
from numpy import linalg
import numpy as np
data
Slicing
# selection du premier element du tableau
data[0,0]
Sélections conditionnées
# selection de tous les clients dont l'age est inférieur à 25
data[data[:,2]<= 25]
Il existe d’autres opérations liées aux matrices, dans la sous-bibliothèque linalg de SciPy :
expm : exponentielle d’une matrice ;
logm : logarithme d’une matrice ;
sinm, cosm, tanm : fonctions trigonométriques sur des matrices ;
sqrtm : racine carrée.
Z 1
Pour calculer x2 dx :
0
from [Link] import quad
def integrand(x):
return x**2
Remarque 2.4. Afin de programmer, nous même les algorithmes de résolutions de nos pro-
blèmes nous utiliserons peu SciPy. Cela, permettra une grande maîtrise des concepts de pro-
grammation mathématique.
Nous pourrons utiliser SciPy, en seconde option, pour l’initiation à l’usage de fonctions de
calcul scientifique dédiées.
2.4. EXERCICES 24
2.4 Exercices
Tous les exercices sont à traiter dans un notebook. Afin de trouver les solutions justes, je vous
recommande :
1. raisonner sur des feuilles de papier ;
2. résoudre mathématiquement les exercices sur vos feuilles ;
3. traduire vous solutions en algorithmes ;
4. simuler vos algorithmes c’est-à-dire traduire vos algorithmes en Python.
Je vous invite à suivre ce lien pour retrouver l’exercice : https: // colab. research. google.
com/ drive/ 1MNhJ5rcO68nI4XcLkdoiAAigLbICpH3t? usp= sharing
Lors de simulations Python, nous programmerons le jeu en utilisant des matrices. Cela inclura à
la fois la programmation du jeu et celle d’un solveur. Nous aborderons les questions suivantes :
• Peut-on toujours gagner à partir de n’importe quelle configuration initiale ?
• Si une solution existe, est-elle unique ?
• S’il existe plusieurs solutions, comment trouver celle avec le nombre minimal de mouve-
ments ?
Les exercices ci-dessous ont pour but de créer le jeu Lights out (Exercices 2 à 4) puis de savoir
dans quelles dimensions le jeu a toujours une solution (Exercice 6) puis de créer un solutionneur
(Exercices 5 à 8).
Exercice 2.2 (Création des matrices croix). Créer une fonction Croix(i, j, n) qui crée la
matrice Ci, j de taille n2 avec des 1 seulement en (i, j) et les voisins verticaux et horizontaux. Il
y aura des zéros aux autres positions.
Les exercices suivants ne sont pas indépendants ! ! ! Je vous invites à lire tous les énoncés avant
de débuter leur résolution.
Exercice 2.3 (Jeu 3×3). Dans cette question, on demande de créer une fonction Lights_Out()
sans variable d’entrée qui lance le jeu avec les indications :
1. Phrase d’accueil dans le jeu,
2. Tirage d’une configuration aléatoire avec la commande [Link]() de Numpy,
3. Affichage de la configuration initiale,
4. Demande de la case où le joueur veut jouer,
5. Récupération du numéro de ligne et de colonne avec la commande input(),
6. Mise à jour de la configuration et affichage de celle-ci.
7. On continue jusqu’à ce que le joueur éteigne toutes les lampes et dans ce cas, on affiche
un message de félicitations et on sort du jeu.
Exercice 2.4 (Matrice de passage). Créer une fonction Matrice_Passage(n) qui prend en
entrée la dimension n et retourne la matrice dont les vecteurs sont les Ci, j exprimés dans la base
canonique de Mn (F2 ). On prendra les Ci, j dans le même ordre que les vecteurs Ei, j de la base
canonique.
Exercice 2.5. On veut déterminer pour quelles dimensions le jeu a toujours une solution.
1. Écrire une boucle qui calcule pour n = 2 à 11, le déterminant de Matrice_Passage(n).
On rappelle que ce déterminant est un nombre dans F2 , c’est-à-dire 0 ou 1. Comme Py-
thon fait les calculs avec des nombres à virgule flottante, il pourra être utile d’utiliser les
commandes round(), int() et ajouter %2 pour avoir le reste dans la division euclidienne
par 2.
2. Donner la liste des dimensions inférieures à 11 pour lesquelles le jeu possède une solution
unique pour toute configuration initiale
2.4. EXERCICES 26
Exercice 2.6 (Inverse de la matrice de passage en dimension 3). Grâce à Python, calculer l’in-
verse de la matrice de passage en dimension 3. On pourra soit :
• faire les calculs avec la commande [Link]() de Numpy, se ramener aux entiers puis
réduire modulo 2 ou charger le package Scipy ;
• changer le type de la matrice avec Matrix() et calculer l’inverse dans M(F2 ) avec la
méthode .inv_mod(2).
Exercice 2.7 (Solutionneur en dimension 3). Écrire une fonction Solution(A) qui prend en
entrée une configuration initiale sous forme d’une matrice A de format 3 × 3 et retourne une
matrice solution S (qui contient des 1 pour les cases où il faut appuyer et des 0 ailleurs).
Exercice 2.8 (Bonus). Créer une interface graphique pour le jeu grâce à la bibliothèque Py-
game. On pourra le faire en dimension 3 puis laisser le choix de la dimension au joueur, ajouter
un bouton pour afficher la solution (Dans ce cas, on tirera la solution au hasard et la configu-
ration initiale sera son image par la matrice de passage) ...
Créez votre premier data frame avec Pandas
3
Comme nous avons pu le voir, les arrays NumPy sont particulièrement efficaces pour traiter des
valeurs numériques. Mais les données, dans la réalité, ne sont pas composées uniquement de
chiffres et de nombres. En effet, on retrouve aussi :
• des catégories ;
• des labels ;
• des dates ;
• du texte brut.
De plus, ces données ont généralement un format prédéfini en analyse de données, où chaque
ligne va correspondre à un individu (au sens statistique du terme), et chaque colonne va être une
caractéristique spécifique des individus. C’est ce que l’on appelle une variable. Voici quelques
exemples pour illustrer cela :
• dans le milieu automobile, chaque individu sera une voiture, et on pourra avoir comme
caractéristiques la puissance du moteur, les dimensions du véhicule, la marque, le modèle,
la couleur, etc. ;
• dans une étude de grande distribution, chaque individu pourra être un produit sur lequel
on aurait plusieurs informations (le prix, la catégorie, etc.) ;
• dans le milieu bancaire enfin, chaque individu sera une personne, sur laquelle on aurait
enregistré le salaire moyen, le genre, ses mensualités de remboursement de prêt, etc. ;
Voilà par exemple à quoi pourrait ressembler ce dernier cas.
27
28
Excel est encore pour beaucoup d’entreprises un format très utilisé pour stocker et déplacer des
données. Mais ce n’est pas le seul, les données peuvent être stockées sous bien des formats
différents. Par exemple, on retrouve régulièrement des fichiers texte ou des fichiers CSV (pour
comma-separated values). Ce sont simplement des fichiers contenant l’ensemble des données
brutes, séparées par un délimiteur.
Voici un exemple avec un jeu de données automobiles, dont le délimiteur est le point-virgule :
La base de données peut également être sous la forme de fichier JSON. Le JavaScript Object
Notation (JSON) est un format standard utilisé pour représenter des données structurées. Cela
ressemble à un gros dictionnaire Python pouvant contenir lui-même d’autres dictionnaires et/ou
listes. C’est une description un peu "réductrice", mais une image vaut mieux que mille mots :
Nous n’aurons malheureusement pas l’occasion d’approfondir le format JSON dans le cadre de
ce cours, mais il existe de nombreuses ressources qui traitent le sujet en détail. Le JSON est un
format très standard dans le monde informatique !
Remarque 3.1. Nous n’avons ici vu que les formats texte, JSON et CSV, mais la liste n’est
naturellement pas exhaustive. De plus, plutôt que de stocker les données dans des fichiers, on a
3.1. GÉNÉREZ UN DATA FRAME 29
Dans ce chapitre nous recherchons un outils qui nous permette de représenter les données avec
le format souhaité (individus/variables), de manipuler différents types de données, et de lire les
données provenant de différentes sources. Cet outil n’est autre que la librairie Pandas, et plus
particulièrement les objets data frame.
Le data frame est un objet Python permettant de représenter les données sous forme de tableau,
où chaque colonne est explicitement nommée. Il reprend les mêmes paradigmes que l’array
NumPy : chaque colonne peut naturellement être d’un type différent, mais une colonne ne peut
contenir qu’un seul type ! Cette organisation simplifie l’accès aux variables, et permet de nom-
breuses manipulations de données plus ou moins complexes.
Question : quel est l’intérêt de la librairie NumPy si Pandas permet de faire mieux ?
Il est important de décompresser le dossier .zip et de placer les fichiers csv dans le même
dossier que le notebook jupyter pour en faciliter l’importation ! Sinon vous devrez utilisez
leurs adresses.
Une fois le data frame importé, commence alors le travail principal : la manipulation de données.
Et avant toute manipulation, il est nécessaire de connaître son jeu de données (dataset en anglais).
data = {
'Nom': ['Alice', 'Kouraogo', 'Alphonse'],
'Âge': [25, 30, 35],
'Ville': ['Paris', 'Lyon', 'Marseille']
}
df_dict = [Link](data)
df_dict.head()
L’index par défaut est une séquence numérique commençant à 0. Les colonnes du DataFrame
sont directement définies par les clés du dictionnaire. Cela n’est pas le cas quand le data frame
est créé à partir d’une liste.
data = [
['Alice', 25, 'Paris'],
['Kouraogo', 30, 'Lyon'],
['Alphonse', 35, 'Marseille']
]
L’index par défaut est une séquence numérique commençant à 0. Les noms des colonnes du data
frame doivent être définies à l’aide de l’argument columns.
Remarque 3.2. Il n’est pas possible (par défaut) d’afficher plus de 60 lignes d’un data frame,
afin de ne pas surcharger inutilement le notebook. De façon globale, chercher à visualiser l’en-
semble d’un data frame n’est généralement pas une bonne pratique. Si cela est tout à fait envi-
sageable avec quelques dizaines de lignes, ça devient vite impossible avec plusieurs millions de
lignes ! Si vous cherchez à afficher plus de 60 lignes, vous aurez finalement comme résultat les 5
premières et dernières lignes du data frame.
Exemple
# chargement du fichier
import pandas as pd
data = pd.read_csv("[Link]")
En premier lieu viennent les dimensions d’un data frame. Combien d’individus (de lignes) ou de
variables (de colonnes) comportent un data frame ? Et combien de colonnes ? Tout comme avec
les arrays NumPy, il est possible de répondre à ces questions via l’attribut .shape :
size = [Link]
print(size[0]) # 228
print(size[1]) # 4
Au-delà du nombre de ligne et de colonnes, on peut avoir envie de connaître les types de cha-
cune de nos variables. On peut accéder à cela très simplement à partir de l’attribut .dtypes :
[Link]
Vous observez que le type des variables e-mail, nom et genre est objet, alors que nous
avons pourtant des chaînes de caractères. Cela est dû au fait que le type objet de Pandas
correspond en fait à une colonne de type chaîne de caractères (ou string).
Enfin, nous avons évoqué précédemment le lien qui peut exister entre Pandas et NumPy. Je
vous propose dès à présent de matérialiser ce lien en transformant notre data frame en array :
De Pandas à Numpy
clients_array = [Link]
display(clients_array)
Nous avons à présent un array NumPy en lieu et place d’un data frame.
3.2. IDENTIFIEZ LES CARACTÉRISTIQUES DE VOTRE DATA FRAME 33
Maintenant que nous sommes au point sur les informations générales d’un data frame. Dans le
chapitre suivant, nous allons découvrir un peu plus en détail ce que Pandas nous permet de faire
en termes de manipulation de data frame.
Manipulez un data frame
4
Dans le chapitre précédent, nous avons importé notre premier data frame mais c’est loin d’être le
dernier. Une fois nos données correctement importées, la suite logique va être de les manipuler
à notre guise.
Voici un cas concret : nous souhaitons accéder à la liste de tous les e-mails des clients ayant
contracté un prêt dans la banque, à partir du data frame clients importé lors du chapitre pré-
cédent, pour créer une liste de diffusion pour des offres commerciales préférentielles. Comment
faire cela avec Pandas ? C’est ce que je vous propose de voir à présent !
Pour accéder à une colonne d’un data frame, il suffit d’utiliser la syntaxe :
nom_dataframe[nom_colonne].
data['email']
On peut même décider de stocker cette variable email (au sens des données) dans une autre
variable (au sens informatique, cette fois !) pour les besoins de la liste de diffusion présentée
ci-dessus. Ici, je crée une variable email dans laquelle je stocke tous les e-mails de ma base
clients :
email = data['email']
34
4.2. DÉCOUVREZ L’OBJET SERIES DE PANDAS 35
Réponse : il suffit de stocker l’ensemble des noms des colonnes auxquelles vous souhaitez
accéder dans une liste. Voilà par exemple comment accéder aux colonnes : nom et l’e-mail :
Vous noterez que les variables s’affichent dans l’ordre dans lequel nous l’avons spécifié (ici : le
nom avec l’e-mail) et non comme elles sont disposées initialement (l’e-mail est avant le nom
dans notre data frame data). Et si vous vérifiez le data frame initial, vous verrez que l’ordre
initial est bien conservé. Ainsi, le processus de sélection nous permet de réorganiser l’ordre des
colonnes comme on le souhaite, sans modifier le data frame initial.
En effet, chaque colonne de votre data frame est de type Series. Vous pouvez vérifier cela par
vous-même via la fonction type : type(data['email']). On obtient le résultat :
[Link].
Il est important de différencier le data frame et la Series. Même s’ils partagent de nombreuses
méthodes, certaines sont néanmoins exclusives à l’un ou l’autre, et cela peut être une source
d’erreur lors de l’implémentation d’analyse de données avec Python.
Remarque 4.1. Une différence évidente, mais que je me permets tout de même de noter : un data
frame a 2 dimensions avec plusieurs colonnes, alors que la Series n’a qu’une seule dimension.
Cela peut fortement vous aider lorsque vous utiliserez certaines méthodes, car vous pourrez
savoir à quel type d’objet vous faites face, en vous basant sur l’affichage que vous avez de ce
dernier (encore une raison d’utiliser la méthode .head).
La Figure 4.1a est relativement « jolie », avec une organisation en tableau, où chaque colonne
(une ici) est explicitement nommée : c’est un data frame. De plus, les informations affichées
en bas sont le nombre de lignes et de colonnes. C’est finalement assez logique, car nous avons
sélectionné ici 1 colonne.
Vous noterez que la Figure 4.1b est un peu plus austère et surtout, que les informations affichées
en bas ne sont pas les mêmes : c’est une Series.
En information, vous avez notamment le nom de la Series, la longueur (ou le nombre de lignes),
et enfin le type de la colonne (entier, chaîne de caractères, etc.).
Une Series ne peut contenir qu’un seul type, alors qu’un data frame, qui est finalement une
collection de Series, peut contenir des colonnes de types différents : une colonne d’entiers, une
colonne de nombres décimaux, etc.
Il est important de garder ces notions en tête lors de vos futures analyses de données. De nom-
breuses méthodes sont communes à ces deux objets, alors que d’autres sont spécifiques. Par
exemple, l’ensemble des attributs vus au chapitre précédent (shape, head, dtypes) existent
pour des Series. Mais certaines méthodes, notamment certaines que nous verrons un peu plus
tard dans ce cours, sont exclusives aux data frames, à cause de leur aspect multidimensionnel.
data['nom'] = 1
Cela aura deux effets : cela va modifier la variable nom existante en remplaçant toutes les valeurs
par 1, et cela transforme également le type de la variable, comme vous pourrez le constater si
vous regardez la Figure 4.2 : nom était de type object avant la transformation (Figure 4.2a) ; elle
est à présent de type integer car 1 est un entier (Figure 4.2b).
Ainsi, si on le remplace par une valeur fixe (comme c’est le cas ici), cela aura pour effet de
remplacer l’ensemble des valeurs de notre colonne par cette valeur fixe, et changera le type de
la colonne dans le type de la valeur fixe spécifiée, qu’elle soit numérique ou non.
On peut également remplacer une colonne par un objet de même dimension. Comprenez par là
une liste, un array ou une series comprenant l’exact même nombre d’éléments. Par exemple, si
4.3. MANIPULEZ LES COLONNES 38
F IGURE 4.2 – Transformation d’une colonne du type object vers le type integer
je souhaite modifier la colonne identifiant par elle-même multipliée par 100, je peux le faire de
la façon suivante :
On peut ainsi décider de remplacer les données de la colonne par des valeurs aléatoires
suivant la loi de Poisson de paramètre 5 :
import numpy as np
data['identifiant'] = [Link](5,[Link][0])
Vous noterez que l’array généré pour remplacer les valeurs a strictement la même dimension
que la colonne qu’il remplace. Vous aurez une erreur si ce n’est pas le cas, donc soyez vigilant
sur cet aspect !
Si vous souhaitez revenir à vos valeurs originales après avoir modifié la colonne nom, vous ne
pouvez pas compter sur Pandas pour conserver un historique des data frames. À la place, vous
pouvez recharger les données originales en utilisant pd.read_csv.
Remarque 4.2. En pratique, on ne modifiera une colonne que lorsqu’on est vraiment sûr de
nous, afin justement de ne pas supprimer par mégarde des données dont on aurait besoin.
# Méthode 1
data['id'] = 100 # création de la colonne
[Link]() #affichage du data frame
Pour résumer, que ce soit pour modifier ou créer une colonne col, la syntaxe sera :
mon_dataframe['col'] = x où x représente soit une valeur fixe, soit un objet de même
dimension que la colonne qu’on souhaite modifier/créer.
Pour supprimer une colonne dans un data frame, il existe (à ce jour) trois méthodes : .drop,
.del, .pop.
# Méthode 1: .drop
[Link](columns = 'id')
Contrairement aux deux options suivantes, la méthode .drop ne modifie pas le data frame
existant, elle renvoie juste une sorte de copie du data frame en y ayant appliqué les modifica-
tions, ici supprimer la colonne id. Vous aurez besoin de remplacer votre data frame pour pal-
lier cela : data_suppresion_definitive = [Link](columns='id', inplace=True)
pour supprimer définitivement la colonne.
# Méthode 2: .del
del data['id']
[Link]()
# Méthode 3: .pop
[Link]('id')
[Link]()
Remarque 4.3. la méthode rename ne modifie pas le data frame existant. Il existe cepen-
dant un argument pour cette méthode (et pour toutes les méthodes similaires) nommé inplace,
qu’il suffit de fixer à Vrai (True) pour pallier cela. Ainsi, [Link](columns={'sexe':
'genre'}, inplace=False) est strictement équivalent à data = [Link](columns={'sexe':
'genre'}).
data['identifiant'].astype(float)
Le mot clé ascending permet de définir si on souhaite trier par ordre croissant ou décroissant.
Question : Comment procéder si on souhaite avoir l’un par ordre croissant et l’autre par ordre
décroissant ?
Voici par exemple comment trier par sexe en ordre croissant et par youre en ordre décroissant :
Maintenant que nous sommes au point avec ces outils, mettons ce que nous avons appris en
pratique !
Exercice d’application 4.1. Nous allons travailler à présent sur notre fichier de prêts immobi-
liers. Chaque ligne du fichier correspond à un prêt qui a été accordé à un de nos clients. Chaque
client est identifié par : son identifiant ! Nous avons les informations suivantes :
• la ville et le code postal de l’agence où le client a contracté le prêt ;
• le revenu mensuel du client ;
• les mensualités remboursées par le client ;
• la durée du prêt contracté, en nombre de mois ;
• le type de prêt ;
• et enfin le taux d’intérêt.
Votre rôle cette fois-ci va être de modifier ce jeu de données pour calculer différentes variables
nécessaires pour identifier les clients à la limite de leur capacité de remboursement, et détermi-
ner les bénéfices réalisés par la banque.
Voici un exercice pour vous entraîner à manipuler un data frame : https: // colab. research.
google. com/ drive/ 1S3FkSdeckSNuuuoiGphc7piPfxgGMZyt? usp= sharing
Filtrez les données du data frame
5
Imaginons les situations suivantes :
• pour une offre commerciale spécifique, on cherche à ne sélectionner que les hommes de
notre data frame ;
• on souhaite identifier les hauts revenus parmi notre clientèle. Pour cela, on souhaite sélec-
tionner tout ceux gagnant mensuellement plus de x ;
• on souhaite identifier les clients dits "risqués", c’est-à-dire ceux qui ont un taux d’endet-
tement supérieur aux 35% légaux.
Jusqu’à présent, nous avons été capables de sélectionner des colonnes spécifiques et de les ma-
nipuler à notre guise. Mais les exemples précédents ne peuvent être satisfaits avec de simples
manipulations de colonnes : il faut appliquer une condition spécifique pour ne sélectionner que
les lignes pertinentes.
Cette opération est ce qu’on appelle une restriction, ou un filtrage. Naturellement, Pandas permet
de faire cela, pour avoir un contrôle total sur nos données.
Exemple 5.1 (Sélection d’un élément). on souhaite sélectionner le nom du premier client de
notre base de données. Comme c’est le premier client, son indice de ligne sera 0. Nous souhai-
tons sélectionner son nom ; la variable nom est la 3ème variable de notre data frame, l’indice de
sa colonne sera donc 2. Le code de sélection serait donc :
mon_dataframe.iloc[0, 2]
'Laurent Dagenais'
42
5.2. UTILISEZ LA SÉLECTION VIA DES CONDITIONS 43
Question : Maintenant, admettons que je souhaite sélectionner le nom des 10 premiers clients,
comment procéder ?
Réponse : Comme avec les arrays, nous pouvons utiliser l’opérateur : pour sélectionner la
plage souhaitée.
La méthode .iloc peut être utile dans certains cas, mais elle est finalement assez limitée. En
effet, elle n’est pas adaptée si on souhaite sélectionner selon une certaine condition (par exemple
tous les revenus supérieurs à x), et il faut absolument connaître l’indice des différentes colonnes.
Cela reste jouable avec 5 − 6 colonnes, mais devient beaucoup plus compliqué lorsqu’on est en
présence de dizaines de colonnes.
Il existe une autre méthode, qui est similaire à .iloc mais qui permet de pallier l’ensemble de
ces inconvénients : la méthode .loc.
C’est à première vue très simple, mais nous allons voir que cette syntaxe peut en pratique devenir
vite complexe, et peut permettre en même temps une grande flexibilité.
5.2. UTILISEZ LA SÉLECTION VIA DES CONDITIONS 44
import pandas as pd
data = pd.read_csv('[Link]')
[Link]()
Une autre option de la méthode .loc est la sélection par index. Avant d’aller plus loin sur cet
aspect, laissez-moi redéfinir la différence entre des index et des indices ! Les indices sont la
position intrinsèque d’un élément au sein d’un tableau. Les index, en revanche, correspondent
à une valeur qui est associée à chaque ligne. C’est ce que vous voyez sur la gauche de votre
data frame : Par défaut, les index correspondent aux indices ! Mais ils peuvent ne pas être numé-
riques ; on pourrait par exemple fixer le nom de la personne comme index, si on est sûr qu’il n’y
aura pas de doublons.
Faisons un simple tri pour bien comprendre la différence entre l’indice et l’index (Figure 5.2) :
Cette situation est intéressante, car si on regarde notre première ligne, son index est 13. Pourtant,
c’est bel et bien la première ligne, donc son indice est 0 ! ! !
Je pense que vous commencez à comprendre la différence : un indice est relatif aux opérations
5.2. UTILISEZ LA SÉLECTION VIA DES CONDITIONS 45
réalisées. Un individu peut avoir le premier indice à un moment, et un tout autre indice en
fonction du tri effectué. En revanche, l’index est intrinsèque aux lignes au sein d’un data frame.
Peu importe les opérations effectuées, que ce soit un tri, une suppression, etc., l’index sera
toujours le même ! La seule condition, c’est que chaque ligne doit avoir un index unique : c’est-
à-dire qu’il ne doit pas y avoir deux fois la même valeur au sein d’un index ; on ne pourra par
exemple pas avoir 2 fois l’index 0.
Réponse : Parce qu’il est possible de faire une sélection au sein d’un data frame selon les
index, avec la méthode .loc.
Remarque 5.1. Il est possible d’accéder à la liste des index d’un data frame via l’attribut
.index. Par exemple, [Link] nous renverra l’ensemble des index du data frame.
5.3. MODIFIEZ UNE SÉLECTION 46
Il est parfois intéressant, après avoir effectué certaines opérations, de réinitialiser ces index –
nous verrons dans les prochains chapitres des exemples concrets, où cela est même nécessaire.
C’est possible via la méthode reset_index().
Réinitialisation d’index
# création d'un data frame trié pour "désordonner" les Index
df_temp = clients.sort_values('nom')
display(df_temp)
# reset_index :
display(df_temp.reset_index())
import pandas as pd
data = pd.read_csv('[Link]')
[Link]()
Un mask à l’intérêt de pouvoir être réutiliser ainsi que celui d’améliorer la lisibilité du code
Exercice d’application 5.1. Certaines demandes ont été spécifiquement formulées par le res-
ponsable du service Prêt de notre établissement. Il souhaite que vous puissiez appliquer les
traitements nécessaires pour lui donner des réponses précises.
Vous allez devoir mettre en application l’ensemble des processus de sélection présentés ci-
dessus, pour répondre à ces différentes demandes :
Voici un exercice pour vous entraîner à filtrer des données dans un data frame : https: //
colab. research. google. com/ drive/ 1JCqeRTFxsCFpUlyNSUn1hNYpKgou82rn? usp= sharing
Maîtrisez les bonnes pratiques de la data
6
visualisation
Il devient donc indispensable pour une entreprise d’avoir des outils pour analyser ces données,
afin d’en tirer des enseignements exploitables au niveau business (des tendances d’achat selon
les périodes, par exemple) et plus globalement, de pouvoir surveiller les différentes activités de
l’entreprise afin d’identifier d’éventuels problèmes.
Toutes les librairies vues jusqu’à présent font partie de ces outils, mais demandent une certaine
technicité, au moins en programmation. Or, la plupart des personnes en charge de la stratégie au
sein d’une entreprise (ceux qu’on appelle les décideurs) n’ont généralement pas ce bagage.
Tout à fait ! C’est ce qu’on appelle la data visualisation (ou dataviz). La data visualisation est un
ensemble de techniques utilisées pour communiquer des informations clés sur un gros volume de
données, afin d’en faciliter la compréhension et la lecture pour tous. Ce domaine s’est vraiment
démocratisé en entreprise dans les années 80, lorsque les entreprises ont pris conscience que
l’analyse de leurs données pourrait aider grandement à la prise de décision !
Remarque 6.1 (Selon Confucius : « Une image vaut mille mots. »). Cette citation résume assez
bien l’idée de la data visualisation. Car finalement, peu importe le choix du graphique ou de la
représentation, l’objectif final reste de résumer une information de façon visuelle, de sorte à ce
que quiconque puisse la comprendre et se l’approprier.
48
6.2. IDENTIFIEZ LE GRAPHIQUE ADAPTÉ 49
Afin de représenter ces données, on peut utiliser des diagrammes circulaires, encore appelés
des camemberts.
Dans le cas d’une variable non numérique, techniquement, c’est une visualisation que nous
avons déjà rencontrée. Car la première étape est d’agréger les données pour compter le nombre
d’occurrences au sein de notre variable, par catégorie ou groupe. Ensuite, on se retrouve simple-
ment dans le cas de comparaison cité ci-dessus : on peut utiliser un diagramme circulaire ou un
diagramme à barres.
6.3. BONNES PRATIQUES DE LA VISUALISATION DES DONNÉES 52
On peut tracer plusieurs points (un pour chaque ligne) en mettant l’une des variables en abscisse
et l’autre en ordonnée : c’est ce qu’on appelle un nuage de points.
La liste n’est naturellement pas exhaustive, et ce cours serait bien trop long s’il fallait tous les
traiter, mais voici cependant un bon échantillon des principales que vous allez être amené à
rencontrer.
Ce sont des « règles » simples qu’il est très vivement conseillé de suivre pour assurer la lisibilité
et la compréhension des visualisations.
6.3. BONNES PRATIQUES DE LA VISUALISATION DES DONNÉES 53
Afin d’éviter d’avoir un graphique illisible, privilégiez la simplicité, quitte à faire plusieurs
graphiques.
À présent, que dire de celui-ci (Figure 6.13) : C’est exactement le même graphique, sauf qu’à
présent, nous avons la grille de lecture pour le lire et le comprendre. Qu’est-ce qui a rendu cela
possible ?
Quatre choses :
• Les titres des axes. On a même ici précisé l’unité !
• La légende pour la compréhension des couleurs.
6.3. BONNES PRATIQUES DE LA VISUALISATION DES DONNÉES 55
F IGURE 6.13 – Un graphique clarifié avec des titres, une légende et des valeurs pertinentes
Faites toujours en sorte de donner l’ensemble des informations pertinentes à votre lecteur,
pour qu’il soit en mesure d’interpréter correctement son graphique.
Question : seriez-vous en mesure de dire dans quelle catégorie, entre B et C, nous disposons
le plus de stock ? Ce n’est pas évident, n’est-ce pas ? Prenons la visualisation pour les mêmes
données mais cette fois-ci avec un diagramme en barres :
F IGURE 6.15 – Un graphique plus adapté pour permettre de comparer les stocks
La différence est d’un coup beaucoup plus nette, la catégorie C possède plus de stock que la
catégorie B. Pourtant, ce sont exactement les mêmes données. C’est pour cela qu’un diagramme
en barres est généralement plus avisé qu’un diagramme circulaire, à partir du moment où il y a
plus de deux groupes à comparer.
En jouant sur les axes, les graduations, les couleurs, le type de graphique, etc., on peut
assez facilement masquer certaines informations sur un graphique, voire lui faire dire autre
chose que ce qu’il veut vraiment dire. Choisissez bien tous ces différents paramètres avec
précaution, afin de ne pas induire votre lecteur en erreur.
Il nous faut donc une librairie pour réaliser ces différents graphiques avec Python. Il en existe
une multitude, et c’est parfois un peu compliqué de comprendre l’intérêt et la plus-value de
l’une par rapport à une autre. C’est pourquoi je vous propose de regarder en détail la librairie
principalement utilisée pour réaliser des visualisations : Matplotlib. Enfin, nous allons plutôt
utiliser pyplot qui est inclus dans Matplotlib.
Importer Matplotlib
import [Link] as plt
57
7.2. TRACEZ VOS PREMIERS GRAPHIQUES 58
scatter. Cette fonction nécessite de définir x et y, qui sont les valeurs à placer en abscisse
et en ordonnée.
[Link](prets['revenu'], prets['taux_endettement'])
[Link](prets['revenu'], prets['taux_endettement'],
s=60, alpha=0.5, c='red', marker='P')
Cette liste n’est pas exhaustive. Vous trouverez la liste complète des arguments sur la documenta-
tion officielle de la fonction : [Link]
[Link].
7.2. TRACEZ VOS PREMIERS GRAPHIQUES 59
On va maintenant représenter le chiffre d’affaires total par agence. Comme nous l’avons vu pré-
cédemment, il existe deux possibilités pour cela : soit un diagramme à barres, soit un diagramme
circulaire. Nous allons réaliser ces deux visualisations.
data = [Link]('ville')['remboursement'].sum()
data = data.reset_index()
Le reset_index est nécessaire car nous allons avoir besoin de la variable ville dans la
création de nos prochains graphiques.
[Link](x=data['remboursement'], labels=data['ville'])
Ce format permet d’afficher la part du chiffre d’affaires total réalisé par chaque agence, avec
2 chiffres après la virgule, et suivie du caractère % .
7.2. TRACEZ VOS PREMIERS GRAPHIQUES 60
Pour utiliser la fonction bar, qui est l’implémentation de Matplotlib des diagrammes à barres, il
faut préciser deux arguments :
• x : les différentes valeurs de la variable non numérique, l’équivalent du labels de pie ;
• height : les valeurs agrégées, équivalent du x de pie .
Représentons maintenant la même information (le chiffre d’affaires total par agence) via un
diagramme à barres.
[Link](height=data['remboursement'], x=data['ville'])
Remarque 7.1. Si vous souhaitez ordonner du plus grand au plus petit, il faudra tricher un petit
peu. En effet, la fonction bar de Matplotlib ne permet pas, par défaut, de réaliser cela. MAIS on
peut tout de même trier le data frame en amont.
7.2.4 Histogramme
Lorsqu’il s’agit de connaissance client dans le milieu bancaire, on arrive assez rapidement aux
questions :
• comment se répartissent nos clients en termes de revenus ?
• a-t-on majoritairement des classes moyennes ?
• des revenus plus modestes ?
Hormis le cadre bancaire, des questions de statistique descriptives se posent généralement.
L’histogramme est particulièrement utile lorsqu’on souhaite avoir une idée de la distribution
d’une variable, et donc particulièrement adéquat pour répondre à cette problématique. La fonc-
tion Matplotlib correspondante est hist. Il suffit de lui passer en paramètre la variable numé-
rique dont on souhaite connaître la distribution :
[Link](prets['revenu'])
En un coup d’œil, on peut déterminer, grâce à l’histogramme, que nous avons majoritairement
des revenus modestes au sein de notre clientèle.
7.2.5 Courbes
On souhaite suivre l’évolution du chiffre d’affaires sur les quatre premiers mois, pour voir la
façon dont il varie, et éventuellement anticiper la suite. Nous avons pour cela à notre disposition
le chiffre d’affaires réalisé par notre banque sur les prêts de janvier à avril 2013.
7.2. TRACEZ VOS PREMIERS GRAPHIQUES 62
evolution_ca = [Link]({
'date': ['2013-01-01', '2013-02-01', '2013-03-01', '2013-04-01'],
"chiffre d'affaire": [183000, 193020, 179032, 219174]
})
evolution_ca
On a ici une évolution dans le temps, donc le choix de représentation le plus pertinent serait de
tracer une courbe. Pour ce faire, on utilise la fonction plot de Matplotlib. Celle-ci prend deux
arguments en entrée : les informations à mettre en abscisse, et celles à mettre en ordonnée.
Remarque 7.2. Comme pour le nuage de points, il existe de très nombreuses options de person-
nalisation. Vous pouvez jouer sur la couleur de la ligne (color ou c), son style (linestyle ou
ls), son épaisseur (linewidth ou lw), si on souhaite ajouter un marqueur en plus de la ligne
(marker), etc. Vous trouverez l’ensemble des possibilités sur la documentation de Matplotlib.
Avec les mêmes données, traçons un graphique plot avec des lignes rouges hachurées, où on
ajoute un point à chaque date.
7.3. CRÉEZ PLUSIEURS GRAPHIQUES SUR UNE MÊME FENÊTRE 63
Ces différents graphiques ne respectent pas vraiment les bonnes pratiques présentées précé-
demment. Ce n’est pas un oublie, on y remédiera dans le chapitre suivant.
Question : représenter le revenu en fonction du taux est assez simple : on peut faire cela via
un nuage de points. Mais comment représenter, en plus, l’information de l’agence ?
Réponse En ajoutant une information supplémentaire à notre graphique, comme la couleur des
points ! Cependant, il n’existe pas d’option par défaut avec Matplotlib pour mettre en couleur
les points. On va être forcés de créer plusieurs graphiques –un par agence– qu’on va superposer
sur une seule et même fenêtre graphique.
data=pd.read_csv('prets_2.csv')
[Link]()
7.3. CRÉEZ PLUSIEURS GRAPHIQUES SUR UNE MÊME FENÊTRE 64
On a pu tracer pour deux villes. Afin de tracer pour toutes les villes ont va utiliser une boucle.
7.3.2 Créez plusieurs sous gures dans une même gure : subplot
La fonction figure de python permet de créer une figure en mui spécifiant des paramètres tels
que : la taille de la figure, la résolution en dvi, ...
# Afficher la figure
[Link]()
Dans le code Python précédent : Dans la fonction figure on a utilisé les arguments :
• figsize=(10, 6) : Définit la taille de la figure en pouces (largeur, hauteur).
7.3. CRÉEZ PLUSIEURS GRAPHIQUES SUR UNE MÊME FENÊTRE 65
Exercice d’application 7.1. Vous êtes en train de préparer le rapport mensuel à présenter
chaque fin de mois à votre responsable. La présentation devra comprendre certains graphiques
clés : vous allez donc devoir utiliser vos compétences en visualisation de données pour produire
les différentes visualisations attendues.
Vous remarquez que ce graphique est difficile à comprendre. Il lui manque en effet :
• l’information globale de ce qui est représenté : le titre du graphique ;
• des informations sur l’axe des ordonnées et sur l’unité utilisée !
66
8.1. MODIFIEZ LES ÉLÉMENTS EXTÉRIEURS 67
Afin de compléter les informations manquantes, nous utiliserons des fonctions supplémentaires
dans notre fenêtre graphique.
[Link](data['ville'], data['chiffre_aff'])
# Ajoutons un titre ayant une police: arial et une taille de 18
[Link]("Chiffre d'affaire réalisé par agence", fontname='Arial', fontsize=18)
F IGURE 8.2 – Graphique de chiffre d’affaires total par agence après ajout d’éléments externes
On a ainsi un graphique complet avec une grille de lecture claire. Il existe cependant d’autres
options pour donner plus de clarté à une visualisation, ou pour en améliorer la qualité esthétique.
8.2. MODIFIEZ LES ÉLÉMENTS INTÉRIEURS 68
F IGURE 8.3 – Graphique de chiffre d’affaires total par agence avant et après modification d’élé-
ments internes
[Link](data['ville'], data['chiffre_aff'])
# Ajoutons un titre ayant une police: arial et une taille de 18
[Link]("Chiffre d'affaire réalisé par agence", fontname='Arial', fontsize=18)
ca = data['chiffre_aff'].tolist()
for i in range(len(ca)):
8.2. MODIFIEZ LES ÉLÉMENTS INTÉRIEURS 69
Remarque 8.1. Ce que nous avons vu n’est qu’une partie de tout ce qu’il est possible de faire
avec Matplotlib. Plus on plonge dans l’aspect de personnalisation des graphiques, plus on se
rend compte que les possibilités sont infinies. Si vous souhaitez aller plus loin, je peux vous
rediriger vers ce notebook Jupyter (https: // nbviewer. org/ urls/ gist. githubusercontent. com/ Jwink3101/
e6b57eba3beca4b05ec146d9e38fc839/ raw/ f486ca3dcad44c33fc4e7ddedc1f83b82c02b492/ Matplotlib_ Cheatsheet ) qui ré-
Exercice d’application 8.1. Les bénéfices mensuels par type de prêt pour l’année 2021 viennent
de sortir au niveau de l’agence où vous travaillez. Dans le cadre du rapport mensuel, il vous est
demandé de réaliser un graphique spécifique représentant cette évolution, par type de prêt.
Je vous invite à vous entraîner avec cet exercice : https: // colab. research. google. com/
drive/ 1jkF6wpXEiHJfPkJOxTWcB-63vXrr_ QRK? usp= sharing
Deuxième partie
Calcul numérique
70
Calcul numérique approché
9
9.1 Erreurs absolue et relative
Afin de définir les notions d’erreurs absolue et relative, nous avons besoin d’introduire les no-
tions de quantités ou de valeurs exactes et de quantités approximatives ou valeurs approchées ;
ce que nous illustrons ci-après au moyen d’exemples.
— Exemples de quantités ou de valeurs exactes :
√
1 2π
1, , 5, 3, π, ln 2, cos , e, ...
3 7
Remarque 9.1. — Plus l’erreur absolue de x∗ est petite, plus x∗ est précise.
— L’erreur absolue sert à déterminer la précision de la valeur approchée x∗ relativement à
la valeur exacte x.
71
9.2. INCERTITUDES ABSOLUE ET RELATIVE 72
Définition 9.3. On appelle incertitude absolue d’une valeur approchée x∗ , tout nombre réel
positif, noté ∆x, vérifiant : E = |x − x∗ | ≤ ∆x ou de manière équivalente : x∗ − ∆x ≤ x ≤ x∗ + ∆x.
∆x
δx = .
|x∗ |
où les ai sont les chiffres du nombre réel x (ai ∈ {0, 1, 2, . . . , 9}), avec am ̸= 0 et m est un entier
naturel appelé rang supérieur du nombre réel x.
9.3. REPRÉSENTATION DÉCIMALE D’UN NOMBRE APPROCHÉ 73
Remarque 9.4. Dans le cas où le nombre réel x est négatif, il suffit de considérer la représen-
tation décimale du nombre y = −x.
π = 3.14159265358 . . .
= 3 · 100 + 1 · 10−1 + 4 · 10−2 + 1 · 10−3
+ 5 · 10−4 + 9 · 10−5 + 2 · 10−6 + . . .
Les exemples suivants illustrent les cas où le zéro n’est pas considéré comme chiffre significatif.
• x∗ = 2.10−3 + 0.10−4 + 1.10−5 + 0.10−6 qui s’écrit en notation décimale x∗ = 0.002010.
Les zéros soulignés ne sont pas des chiffres significatifs.
• x∗ = 3.106 +0.105 +0.104 +7.103 +0.102 +0.101 +0.100 qui s’écrit en notation décimale
x∗ = 3007000. Les zéros soulignés ne sont pas des chiffres significatifs.
Définition 9.4. On appelle chiffre significatif (c.s.) d’un nombre approché, tout chiffre dans sa
représentation décimale différent du zéro ; et un zéro s’il se trouve entre deux chiffres significatifs
ou s’il constitue un chiffre conservé.
9.4. CHIFFRES SIGNIFICATIFS EXACTS D’UN NOMBRE APPROCHÉ 74
2. Si on approche le nombre 1789 à la centaine près par 1800, à la place des chiffres négligés
8 et 9, on introduit deux zéros. Ils ne servent qu’à fixer l’ordre de grandeur du nombre
pris comme valeur approchée ; ce ne sont pas des chiffres significatifs. Par contre si on
approche le nombre 1789.7 à l’unité près par le nombre 1790, le zéro est alors un chiffre
significatif.
Définition 9.5. Un chiffre significatif de x∗ est dit exact (c.s.e) si l’erreur absolue de ce nombre
ne dépasse pas une demi-unité de rang du chiffre significatif, c’est-à-dire que :
Ainsi :
— Le n-ième c.s après la virgule est exact si : |∆x| ≤ 0.5 · 10−n .
— Le n-ième c.s avant la virgule est exact si : |∆x| ≤ 0.5 · 10n−1 .
Attention ! Un c.s.e de x∗ ne coïncide pas nécessairement avec le c.s. correspondant dans x.
Proposition 9.1. — Si un c.s est exact, tous les c.s à sa gauche sont exacts.
— Si un c.s n’est pas exact, tous ceux à sa droite ne le sont pas.
Remarque 9.5. Si l’erreur absolue de x∗ ne dépasse pas une unité de rang du dernier c.s, on
dit que x∗ est une valeur approchée au sens large ou encore qu’il est une valeur approchée à
chiffres significatifs exacts au sens large.
Une méthode habituelle pour tronquer un nombre pour ne garder qu’un nombre fini de chiffres
significatifs est l’arrondi.
Règle d’arrondissement. Pour arrondir un nombre jusqu’à n c.s, on élimine les chiffres à
droite du n-ième c.s conservé si l’on se trouve après la virgule, sinon on remplace par des zéros.
Dans les deux cas on procède de la manière suivante :
1. Si le (n + 1)-ième c.s est strictement plus grand que 5, on augmente le n-ième chiffre de
1. Si, par contre, il est strictement plus petit que 5, les chiffres retenus restent inchangés.
2. Si le (n + 1)-ième c.s est égale à 5 alors deux cas sont possibles :
— Tous les chiffres rejetés, situés après le (n + 1)-ième c.s, sont des zéros : on applique
la règle du chiffre pair, c’est-à-dire que le n-ième chiffre reste inchangé s’il est pair.
On lui ajoute 1 s’il est impair.
— Parmi les chiffres rejetés, situés après le (n + 1)-ième c.s, il existe au moins un qui
soit non nul : on ajoute 1 au n-ième chiffre.
f (x) = 0 (10.1)
s’il vérifie
f (x∗ ) = 0. (10.2)
Résoudre l’équation (10.1) consiste à déterminer tous les nombres réels x∗ ∈ D f tels que (10.2)
soit vérifiée. En d’autres termes, on cherche à déterminer l’ensemble R = {x ∈ D f : f (x) = 0},
qui est l’ensemble des racines de l’équation (10.1). Il n’est pas toujours possible de résoudre
complètement ce problème pour toutes les formes de fonctions f . L’ensemble R peut, en effet,
avoir un grand nombre de structures possibles.
Définition 10.2. On dit qu’une racine x∗ de l’équation (10.1) est séparable si on peut trouver
un intervalle [a, b] ⊆ D f tel que x∗ soit la seule racine de cette équation dans cet intervalle ; ou
encore si R ∩ [a, b] = {x∗ }. La racine x∗ est alors dite séparée (on dit aussi racine isolée).
76
10.2. SÉPARATION DES RACINES 77
• soit on trace, expérimentalement (à l’aide d’un logiciel) ou par étude des variations de f ,
le graphe de la fonction f , puis on cherche son intersection avec l’axe Ox ;
• soit on décompose f en deux fonctions f1 et f2 de sorte que l’équation (10.1) puisse
s’écrire de manière équivalente : f1 (x) = f2 (x), puis on cherche les points d’intersection
des graphes de f1 et f2 , dont les abscisses sont les racines de l’équation (10.1).
Remarque 10.1. Les fonctions f1 et f2 sont souvent choisies de sorte que leurs courbes soient
simples et connues.
—• De même, si deux racines sont très voisines, on risque de ne pas les séparer dans le
processus ci-dessus.
— L’intervalle de départ [a, b] doit être suffisamment grand afin de contenir les racines éven-
tuelles de l’équation (10.1) ; mais, sauf dans des cas particuliers, il est difficile d’estimer
correctement sa longueur.
dans lequel on part d’une valeur (approchée) x0 pour calculer x1 , puis à l’aide de x1 on calcule
x2 , etc.
La formule (10.3) est dite formule de récurrence. Le procédé est dit convergent si la suite des
itérations (xk )k est convergente.
Parmi les méthodes numériques en général et les méthodes itératives en particulier, les plus
puissantes permettant la résolution approchée des équations du type (10.1), figure la méthode
suivante.
f (x0 ) f ′′ (ξ ) ∗
x∗ = x0 − ′
− ′
(x − x0 )2 . (10.4)
f (x0 ) 2 f (x0 )
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 79
En négligeant le reste
f ′′ (ξ ) ∗
R2 = − (x − x0 )2 ,
2 f ′ (x0 )
la quantité
f (x0 )
x1 = x0 −
f ′ (x0 )
dans (10.4), qu’on notera x1 , constitue alors une valeur approchée améliorée de x∗ . En itérant le
procédé on déduit la formule de récurrence :
f (xk )
xk+1 = xk − , k ∈ N.
f ′ (xk )
ce qui donne :
f (xk )
xk − x∗ = .
f ′ (ξk )
D’autre part :
f (xk ) f (xk )
xk+1 = xk − =⇒ xk+1 − xk = .
f ′ (xk ) f ′ (xk )
En faisant l’approximation f ′ (ξ ) ≃ f ′ (xk ) on obtient finalement :
|xk − x∗ | ≃ |xk+1 − xk |.
Ainsi, si on veut calculer une valeur approchée de x∗ ayant la n-ième décimale qui est exacte
(c’est-à-dire, avec la précision ε = 0.5 · 10−n ), il suffit d’aller dans les itérations jusqu’à ce que
xk vérifie :
|xk+1 − xk | ≤ 0.5 · 10−n . (10.5)
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 80
f (xk )
xk+1 = xk − , k ∈ N.
f ′ (xk )
f (x)
On a donc : xk+1 = g(xk ) où g(x) = x − . Comme
f ′ (x)
alors pour x = x∗ , x∗ étant une racine séparée de l’équation f (x) = 0, on a g′ (x∗ ) = 0 (puisque
f (x∗ ) = 0) et de là |g′ (x∗ )| = 0 < 1 au voisinage de x∗ .
Conséquence : Les conditions i) et ii) du théorème du point fixe (Théorème 10.4) sont donc
réalisées, et par suite on a convergence de la suite des itérations (xk )k vers x∗ .
C’est dans ce but qu’on choisit comme voisinage de x∗ un intervalle [a, b] de sorte que :
1. x∗ ∈ [a, b],
2. f est de classe C 2 sur [a, b],
3. f ′ ̸= 0 sur [a, b].
On vérifiera ci-après qu’avec une condition supplémentaire sur l’intervalle [a, b], la suite (xk )k
converge vers x∗ , indépendamment du choix de la valeur approchée initiale x0 ∈ [a, b].
Remarque 10.3. • f étant de classe C 2 sur [a, b], f ′′ est continue sur [a, b] et donc bornée
sur [a, b] par une constante M > 0 de manière à ce qu’on ait :
Sous les conditions (1), (2) et (3) ci-dessus, faisons un développement de Taylor de f à l’ordre
1 au voisinage de xk pour obtenir :
1
f (x) = f (xk ) + f ′ (xk )(x − xk ) + f ′′ (ξk )(x − xk )2 où ξk ∈]x, xk [.
2
1
0 = f (xk ) + f ′ (xk )(x∗ − xk ) + f ′′ (ξk )(x∗ − xk )2 , où ξk ∈]x∗ , xk [.
2
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 81
Or
f (xk ) f (xk )
xk+1 = xk − ′
=⇒ − ′ = xk+1 − xk .
f (xk ) f (xk )
D’où, après simplification :
f ′′ (ξk )(x∗ − xk )2
xk+1 − x∗ = ,
2 f ′ (xk )
soit
f ′′ (ξk ) ∗
xk+1 − x∗ = (x − xk )2 .
2 f ′ (xk )
Comme | f ′′ (x)| ≤ M et | f ′ (x)| ≥ m > 0, on aboutit alors à :
M.|xk − x∗ |2
|xk+1 − x∗ | ≤ . (10.6)
2m
k −1 k
|xk − x∗ | ≤ C2 (b − a)2 ,
ou encore k
∗ [C(b − a)]2
|xk − x | ≤ .
C
Il y a donc convergence vers x∗ si :
M
C(b − a) = (b − a) < 1,
2m
et c’est pour cette raison que l’on choisit [a, b] de longueur telle que :
2m
b−a < .
M
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 82
Conclusion : Si en plus des conditions (1), (2) et (3), on choisit l’intervalle [a, b] tel que
2m
b−a < , alors : ∀x0 ∈ [a, b], l’algorithme de Newton-Raphson converge (vers x∗ ).
M
Remarque 10.4 (Choix de la valeur approchée initiale x0 ). La valeur approchée initiale x0 est
généralement choisie de manière à ce que : f (x0 ) · f ′′ (x0 ) > 0. En particulier on prend x0 = a
ou x0 = b, s’il vérifie cette condition.
Afin de montrer que f possède une seule racine sur [1, 2], on aurait également pu tracer
la courbe de la fonction f sur l’intervalle [1, 2].
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 83
On arrête les itérations dès que |xk+1 − xk | ≤ 0.5 × 10−3 est vérifiée.
Commentaire : Le choix de la 3eme décimale dans le critère d’arrêt est dicté par le fait que
la racine x∗ étant contenue dans l’intervalle [1, 2], elle s’écrit nécessairement sous la forme
x∗ = 1, . . . . Comme par hypothèse le nombre de c.s.e exigé est 4, il vient que la racine x∗ doit
être calculée avec 3 décimales exactes.
Les itérations sont reportées dans le tableau suivant où les calculs sont faits avec 1 décimale de
plus.
k xk E = |xk+1 − xk |
0 2
1 1.5455 0.4545
2 1.3596 0.1859
3 1.3258 0.0338
4 1.3247 0.0011
5 1.3247 0
Ainsi l’algorithme de Newton-Raphson nécessite 5 itérations afin d’obtenir une valeur appro-
chée de la racine de f (x) = 0 ayant 4 c.s.e (ou encore, 3 décimales exactes).
où F et G sont des fonctions données des variables indépendantes x et y. Soit (x0 , y0 ) une valeur
approchée d’une solution exacte (x∗ , y∗ ). Posons :
(
x∗ = x0 + ε0
où ε0 et λ0 sont les erreurs absolues de x0 et y0 .
y∗ = y0 + λ0
0 = F(x∗ , y∗ ) = F(x0 + ε0 , y0 + λ0 )
∂F ∂F
= F(x0 , y0 ) + (x0 , y0 ) · ε0 + (x0 , y0 ) · λ0 + R0
∂x ∂y
0 = G(x∗ , y∗ ) = G(x0 + ε0 , y0 + λ0 )
∂G ∂G
= G(x0 , y0 ) + (x0 , y0 ) · ε0 + (x0 , y0 ) · λ0 + R1
∂x ∂y
−1
! ∂F ∂F !
ε0 ∂x ∂y F
= −
∂G ∂G
+ termes d’ordres supérieurs à 1 en ε0 et λ0
λ0 G (x ,y )
0 0
∂x ∂ y (x0 ,y0 )
En négligeant le reste qui est formé des termes d’ordres supérieurs à 1, la quantité :
−1
! ∂F ∂F !
x0 ∂x ∂y
F
−
∂G ∂G
y0 G (x ,y )
0 0
∂x ∂ y (x0 ,y0 )
P(n) (x) = 0.
des racines réelles simples de l’équation, que leur localisation. Il s’agit des outils suivants :
Théorème 10.2 (Localisation). Les racines réelles de l’équation P(n) (x) = 0 sont contenues dans
1
l’intervalle ] − T, T [ avec : T = 1 + · max{|ai | : i ∈ J1, . . . , nK}.
|a0 |
Proposition 10.1. Si la suite {Si (ξ ) : i ∈ J1, . . . , nK} est d’ordre p, c’est-à-dire que
S p+1 (x) = 0, p < n, alors les racines multiples du polynôme P(n) (x) sont les racines simples du
polynôme S p (x).
x3 − 3x2 + x − 3 = 0. (10.7)
Localisation des solutions. Celles-ci sont contenues dans l’intervalle [−T, T ] avec
1 1
T = 1+ max{|ai |; i = 1, 2, 3} = 1 + max{| − 3|, |1|, | − 3|} = 1 + 3 = 4.
|a0 | 1
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 88
Ainsi, les solutions de l’équation (10.7), si elles existent, se trouvent contenues dans l’intervalle
[−4, 4].
Nous avons alors résumé dans le tableau suivant les différents changements de signe des termes
de la suite de Sturm, ainsi que leur nombre :
Résolution par la méthode de Newton-Raphson. Pour cela nous commençons par réduire l’in-
tervalle contenant la racine recherchée x∗ . Nous avons P(3) (0) = −3 et P(3) (4) = 69 > 0, donc
x∗ ∈ [0, 4]. Prenons par exemple x0 = 0. Nous avons alors :
Ainsi, nous obtenons une suite stationnaire qui donne dans ce cas particulier, non pas une racine
approchée mais la racine exacte égale à 3.
L’algorithme 4 est une fonction qui évalue un polynôme à une valeur donnée x. Elle parcourt
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 89
Algorithme 4 : EvaluerPolynome
Input : polynome, x
Output : La valeur du polynôme évaluée en x
Initialiser valeur ← 0;
for chaque terme dans polynome do
valeur ← valeur + ([Link] f f icient × ([Link] ));
end
return valeur;
nous avons besoin de la connaissance de la dérivée de f . Dans certaines circonstances (si f pro-
vient d’un calcul expérimental par exemple), on ne peut calculer f ′ . L’idée est alors de remplacer
f ′ par le taux d’accroissement de f sur un petit intervalle.
f (x1 ) − f (x0 )
Le taux d’accroissement de f sur [x0 , x1 ] est donné par : τ1 = et l’équation de la
x1 − x0
sécante (S) au graphe de f aux points (x0 , f (x0 )) et (x1 , f (x1 )) s’écrit :
f (x1 ) − f (x0 )
y − f (x1 ) = τ1 (x − x1 ) + f (x1 ) = (x − x1 ) + f (x1 ). (10.8)
x1 − x0
culièrement utile pour les fonctions continues sur un intervalle où la fonction change de signe,
garantissant ainsi l’existence d’une racine dans cet intervalle.
L’idée est la construction d’une suite d’intervalles de plus en plus petits contenant une racine
isolée de l’équation f (x) = 0. L’outil utilisé est le Théorème des valeurs intermédiaires.
Théorème 10.3 (Théorème des valeurs intermédiaires). Soit f : [a, b] −→ R une fonction conti-
nue, telle que : f (a) · f (b) < 0. Alors, il existe au moins x∗ ∈]a, b[ tel que f (x∗ ) = 0.
Ik = [ak , bk ], k ∈ N∗
ak + bk
dont les extrémités sont définies comme suit : on pose xk = et on procède au test suivant :
2
Si f (a ) f (x ) < 0 alors [a , x ] = [a , b ] = I ;
k k k k k+1 k+1 k+1
sinon [x , b ] = [a , b ] = I .
k k k+1 k+1 k+1
bk − ak bk−1 − ak−1 b0 − a0
bk+1 − ak+1 = = 2
= · · · = k+1 .
2 2 2
bk − ak b0 − a0
|x∗ − xk | ≤ bk+1 − ak+1 = = k+1 .
2 2
Donc, si on souhaite calculer une valeur approchée xk de x∗ ayant la n-ième décimale qui est
exacte (précision ε = 0.5 · 10−n ), il suffit de poser
b0 − a0
k+1
≤ 0.5 · 10−n .
2
Ce qui revient à ce qu’on aille dans les itérations jusqu’à ce que k vérifie l’inégalité :
Ainsi, les itérations s’achèvent à la k0 -ième étape où k0 est le premier entier naturel vérifiant
(10.9).
Dans la résolution d’équations non linéaires, la méthode dichotomique est sûre mais a une
convergence lente.
Exercice d’application 10.7. Sachant que l’équation x3 − x − 1 = 0 possède une seule racine
positive comprise entre 1 et 2,
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 93
1. déterminer le nombre d’itérations suffisantes pour trouver cette racine avec 4 chiffres
significatifs exacts en utilisant la méthode de dichotomie ;
2. calculer cette racine avec 2 chiffres significatifs exacts en utilisant la dichotomie.
Donc, on prend k0 = 4.
Définition 10.5. Soit f : R −→ R une fonction dont le domaine de définition est une partie D f de
R. On suppose que f est continue sur D f . On dit que x∗ ∈ D f est un point fixe de f si f (x∗ ) = x∗ .
Théorème 10.4 (Théorème du point fixe). Supposons que f est définie sur l’intervalle [a, b] et
satisfait aux conditions suivantes :
(i) f ([a, b]) ⊆ [a, b], i.e., ∀x ∈ [a, b], a ≤ f (x) ≤ b. On dit alors que l’intervalle [a, b] est stable
par l’application f .
(ii) f est strictement contractante, i.e., ∃ L ∈ R, 0 ≤ L < 1 tel que
Alors, f admet un point fixe unique x∗ ∈ [a, b]. De plus l’algorithme, dit du point fixe, défini par :
x ∈ [a, b]
0
x
k+1 = f (xk ), k∈N
converge vers x∗ .
Théorème 10.5 (Théorème d’Ostrowski). Soit x∗ un point fixe d’une fonction f continue et
dérivable sur [a, b] contenant x∗ . Si | f ′ (x)| ≤ L′ < L < 1 sur [c, d] alors il existe un intervalle
[c, d] ⊂ [a, b] tel que la suite (xk ) converge vers x∗ pour tout x0 ∈ [c, d].
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 95
La convergence de la suite xk+1 = f (xk ) vers x∗ sur [c, d] est encore plus rapide que celle obtenue
sur l’intervalle [a, b] car : |x∗ − xk | ≤ L′k |x∗ − x0 |.
Le choix d’un intervalle plus petit permet souvent d’obtenir une meilleure estimation du point
fixe, surtout si L′ est significativement plus petit que L, ce qui accélère la convergence.
Ainsi, si on souhaite calculer une valeur approchée xk de x∗ ayant la n-ième décimale qui est
exacte (précision ε = 0.5 · 10−n ), il suffit d’arrêter les itérations dès que k vérifie :
obtenue en posant Lk (b − a) ≤ 0.5 · 10−n . Les itérations s’arrêtent donc à la k0 -ième étape où k0
est le premier entier vérifiant (10.11).
1−L
|xk+1 − xk | ≤ 0.5 · 10−n . (10.12)
L
Remarque 10.8. En général L est assez petit de sorte que 2L < 1 d’où L < 1 − L. Ce qui donne :
L
|xk − xk+1 | ≤ |xk − xk+1 |.
1−L
Conséquence : au lieu du critère d’arrêt (10.12), on prend souvent comme critère d’arrêt la
condition suivante :
|xk+1 − xk | ≤ 0.5 · 10−n .
Ek2 ′′ ∗
xk+1 = f (xk ) = f (x∗ + Ek ) = f (x∗ ) + Ek f ′ (x∗ ) + f (x ) + . . . .
2!
Comme (Ek ) est une suite convergente vers 0, il apparaît clairement que plus la valeur | f ′ (x∗ )|
est petite, plus la convergence est rapide. □
λ x + f (x)
g(x) = .
1+λ
Comme f (x) = x ⇐⇒ g(x) = x, alors x∗ est un point fixe de f si et seulement si il l’est pour G.
On a :
λ + f ′ (x)
g′ (x) =
1+λ
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 97
donc :
λ + f ′ (x∗ )
g′ (x∗ ) = .
1+λ
Il suffit alors de prendre λ voisin de − f ′ (x∗ ) pourvu que f ′ (x∗ ) soit petit (pour qu’on puisse
appliquer l’algorithme du point fixe à f ). Donc, d’après le Lemme 10.1, la convergence sera
plus rapide que celle donnée par f (x) = x.
Algorithme d’accélération.
1. Calculer x0 , x1 , . . . , xn par la méthode lente :
x ∈ [a, b]
0
x
k+1 = f (xk ), k = 0, 1, . . . , n − 1
λ x + f (x)
g(x) = .
1+λ
Exercice d’application 10.8. Déterminez les racines des équations non linéaires simultanées
suivantes
y = −x2 + x + 0.75
y + 5xy = x2
10.3. APPROXIMATION DES RACINES : MÉTHODES ITÉRATIVES 98
en utilisant :
1. L’itération à point fixe.
2. La méthode de Newton-Raphson.
Utilisez des suppositions initiales de x = y = 1.2 et discutez des résultats.
L’objectif est de déterminer les racines x et y qui satisfont ces deux équations en utilisant deux
méthodes : l’itération à point fixe et la méthode de Newton-Raphson.
1. Méthode du point fixe Pour résoudre cette équation par itération à point fixe, nous ré-
arrangeons la première équation pour obtenir une forme itérative pour y en fonction de x. La
deuxième équation est déjà en termes de y, et nous l’utiliserons directement pour vérifier la
solution à chaque itération.
La première équation devient : y = −x2 + x + 0.75 et la deuxième équation peut être réécrite
x2
pour exprimer y en fonction de x : y = . Nous pouvons alors utiliser ces expressions pour
1 + 5x
itérer l’algorithme 7 afin d’obtenir les solutions.
∂ f1 ∂ f1 ∂ f2 ∂ f2
= 5y − 2x, = 5x, = −2x + 1, = −1
∂x ∂y ∂x ∂y
Nous formons la matrice Jacobienne J et la solution par Newton-Raphson est donnée par :
! !
xn+1 xn
= − J −1 · F(xn , yn )
yn+1 yn
où F(xn , yn ) est le vecteur des fonctions f1 et f2 . Avec ces éléments on peut itéré l’algorithme 2
afin d’obtenir les solutions.
10.4. IMPLÉMENTATION SCIPY D’ÉQUATIONS NON LINÉAIRES 99
import numpy as np
from [Link] import fsolve
# Définir la fonction
def func(x):
return [x[0] + x[1] - 2, x[0]**2 + x[1]**2 - 4]
# Estimation initiale
x0 = [1, 1]
# Afficher la racine
print("x*=", racine)
La fonction [Link] est basée sur les algorithmes hybrides de Powell, spéci-
fiquement les algorithmes hybrd et hybrj de la bibliothèque MINPACK. Ces algorithmes sont
conçus pour résoudre des systèmes d’équations non linéaires en utilisant une combinaison de la
méthode de Newton et de la méthode de Gauss-Newton, avec des ajustements pour améliorer
la robustesse et la convergence. L’algorithme hybride de Powell est particulièrement efficace
pour les problèmes où les dérivées peuvent être difficiles à calculer ou lorsque les solutions
sont sensibles aux conditions initiales. Cependant, fsolve ne permet pas de spécifier directe-
ment une autre méthode de résolution. Si vous avez besoin de spécifier une méthode particu-
10.4. IMPLÉMENTATION SCIPY D’ÉQUATIONS NON LINÉAIRES 100
lière, vous devrez utiliser une autre fonction de SciPy qui permet de choisir la méthode, comme
[Link].
import numpy as np
from [Link] import root
# Définir la fonction
def func(x):
return x**2 - 4
# Estimation initiale
x0 = [Link]([1.0])
101