Vous êtes sur la page 1sur 38

Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Introduction à l’IA et au Deep Learning

TP N°1 : PRISE EN MAIN DE PYTHON

Niveau : 2ère année MPTRT Année universitaire : 2021/2022

Ce TP a pour but de vous initier au langage Python et à son environnement afin de


pouvoir réaliser par la suite les différents ateliers traitant de quelques algorithmes
classiques de l’IA et de l’apprentissage automatique. Ce TP décrit les principaux
objets et instructions de Python et explique comment exécuter des commandes ou un
programme Python soit en ligne de commande soit depuis un éditeur Python.
D’autres instructions et astuces seront découvertes dans les TP qui suivent.
Il est impératif dans ce TP de retaper les bout de code donnés et de faire les exercices
demandés.

I. Variables et types
Les objets manipulés par Python, au moment où ils sont créés, sont stockés dans la
mémoire de l’ordinateur. Un nom de variable est une suite de caractères qui renvoie à
une adresse mémoire où a été créé un objet. Les noms de variables autorisés sont des
séquences de lettres (majuscules ou minuscules) et de chiffres qui débute toujours
par une lettre. La casse est significative. Il existe quelques mots réservés ne pouvant
faire office de nom de variable (def, if, while, True, False...).
Le type d’une variable correspond à la nature de celle-ci. Les trois principaux types
dont nous aurons besoin dans un premier temps sont les entiers (integer ou int), les
nombres décimaux (float) et les chaînes de caractères (string ou str). Bien sûr, il
existe de nombreux autres types (par exemple, les booléens bool, les nombres
complexes, etc.). Sous Python, il n’est pas nécessaire de définir le type d’une variable
avant de l’utiliser : on dit que le langage est à typage dynamique (le type d’une
variable est déduit selon la valeur qui lui est affectée)

1. Opérations sur les types numériques (int ou float)


Le type int représente l’ensemble des entiers relatifs et float celui des entiers réels.
Les quatre opérations arithmétiques de base se font de manière simple sur les types
numériques : (+) Addition, (-) Soustraction, (*) multiplication, ( /) division, (**)
puissance.
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Le résultat de ces opérations dépend de leurs opérandes, si vous utilisez des entiers
comme opérandes pour l’addition, la soustraction, la multiplication ou l’opérateur de
puissance, le résultat sera de type entier, toutefois si vous mélangez les types entiers
et floats, le résultat est renvoyé comme un float. L’opérateur / renvoie
systématiquement un float.
Pour obtenir le quotient et le reste d’une division entière, on utilise respectivement
les symboles (//) et modulo (%).
il existe des opérateurs « combinés » qui effectue une opération et une affectation en
une seule étape (+=, -=, *=, /=).
>>> i = 0
>>> i = i + 1
>>> i
1
>>> i += 1
>>> i
2
>>> i *= 2
>>> i
4

2. Opérations sur les chaînes de caractères


Voici une liste non exhaustive d’opérations autorisées sur les chaines de caractères
(+) : Concaténation
(*) : Répétition
(ch[i]) : Accès à l’élément d’indice i de la chaîne ch
(ch[i :j]) : Extraction de sous chaîne à partir de l’indice i et jusqu’à l’indice j de ch
Len(ch) : longueur de ch

3. Opérations sur les booléens


Ce type autorise deux valeurs possibles True or False (attention à la casse). Les
opérateurs applicables sur ce type sont : (==, !=, <=, >=, <, >, or, and, not).
La commande bool() évalue l’argument comme un booléen selon la règle suivante : si
la donnée est booléenne elle retourne sa valeur, si la donnée est 1 elle retourne True
sinon elle retourne False.

4. Conversion de type
En programmation, on est souvent amené à convertir les types, c’est-à-dire passer
d’un type numérique à une chaîne de caractères ou vice-versa. En Python, rien de
plus simple avec les fonctions int(), float() et str().
>>> i = 3
>>> str (i)
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

'3'
>>> i = '456'
>>> int (i)
La commande type permet d’obtenir le type d’un objet.
>>> X=input(’Quel âge avez-vous ? ’)
Quel âge avez-vous ? 17
>>> X,type(X)
(’17’, <class ’str’>)

II. Instructions élémentaires


1. Affectation
Pour affecter (ou assigner) une valeur à une variable on utilise le signe égal.
La commande ci-dessous signifie que désormais le caractère x renvoie à la valeur 1.
>>> x=1
Le langage Pyhton offre la possibilité de réaliser en une seule instruction plusieurs
affectations :
- Affectations successives. La commande ci-après signifie que x représente la
valeur 1 et y représente la valeur x (donc 1).
>>> y=x=1

- Affectations parallèle. La commande ci-après signifie que a prend la valeur 1 et


b prend la valeur 2.
>>> a,b=1,2

La commande ci-dessous permet d’échanger les valeurs des deux variables.


>>> x,y=y,x

2. Instructions d’entrée sortie


a. La fonction d’affichage print()
La fonction print() affiche l’argument qu’on lui passe entre parenthèses et un retour à
ligne. Ce retour à ligne supplémentaire est ajouté par défaut. Si toutefois, on ne veut
pas afficher ce retour à la ligne, on peut utiliser l’argument par « mot-clé » end :
>>> print (" Hello world !")
Hello world !
>>> print (" Hello world !", end ="")
Hello world !>>>
La fonction print() peut également afficher le contenu d’une variable quel que soit
son type. Il est également possible d’afficher le contenu de plusieurs variables (quel
que soit leur type) en les séparant par des virgules :
>>> x = 32
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

>>> nom = " John "


>>> print (nom , "a", x, " ans ")
John a 32 ans
Vous remarquerez que pour afficher plusieurs éléments de texte sur une seule ligne,
nous avons utilisé le séparateur « , » entre les différents éléments. Python a
également ajouté un espace à chaque fois que l’on utilisait le séparateur « , ». On peut
modifier ce comportement en passant à la fonction print() l’argument par mot-clé
sep :
>>> x = 32
>>> nom = " John "
>>> print (nom , "a", x, " ans ", sep ="")
Johna32ans
>>> print (nom , "a", x, " ans ", sep =" -")
John -a -32 - ans
Pour afficher deux chaînes de caractères l’une à côté de l’autre, sans espace, on peut
soit les concaténer en utilisant « + », soit utiliser l’argument par mot-clé sep avec une
chaîne de caractères vide :
>>> ani1 = " chat "
>>> ani2 = " souris "
>>> print (ani1 , ani2 )
chat souris
>>> print ( ani1 + ani2 )
chatsouris
>>> print (ani1 , ani2 , sep ="")
chatsouris
Python a introduit les f-strings pour mettre en place l’écriture formatée permettant
d’afficher des variables avec un certain format, nous vous laissons le soin de chercher
la syntaxe de cette écriture.

b. La fonction de saisie input()


La commande input permet de récupérer les entrées de l’utilisateur sous forme de
chaîne de caractère
>>> s=input()
>>> ▌
>>> s=input("Saisir une chaine :")
Saisir une chaine :
>>> ▌

III. Les commentaires


En Python, les lignes de commentaires commencent par le symbole # (CTRL + /
permet de commenter une ligne).
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

En Python il n’y a pas, comme dans certains langages, d’accolade ouvrante ou


fermante pour délimiter un bloc d’instructions. Les blocs d’instructions en python
sont délimités par ":" puis des tabulations : toutes les instructions consécutives à un
":" et débutant par un même nombre de tabulations appartiennent à un même bloc
d’instructions.

IV. Les structures conditionnelles


La syntaxe d’une structure conditionnelle if est la suivante :
if condition1: # Ne pas oublier les deux points
Traitement1 # Ne pas oublier la tabulation en debut de ligne
elif condition2: # Ne pas mettre de tabulation et ne pas oublier les deux points
Traitement2 # Ne pas oublier la tabulation en debut de ligne
else: # Ne pas mettre de tabulation et ne pas oublier les deux points
Traitement 3 # Ne pas oublier la tabulation en debut de ligne
Exemple
a=0
if a==0:
print(’0’)
elif a==1:
print(’1’)
else:
print(’2’)

V. Les boucles
1. Boucle for
Sa syntaxe est comme suit :
for itérateur in range(n): # Ne pas oublier les deux points
Traitement # Attention ne pas oublier une tab. en debut de ligne sinon erreur

Exemple
for i in range(10):
x=2
print(x*i)

2. Boucle while
La syntaxe de cette structure est la suivante :
While condition: # Ne pas oublier les deux points
Traitement # Ne pas oublier la tabulation en debut de ligne
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Exemple
a=0
while (a<12):
a=a+1
print(a, a**2,a**3)

3. Instructions break et continue


Ces deux instructions permettent de modifier le comportement d’une boucle (for ou
while) avec un test.
L’instruction break stoppe la boucle.
>>> for i in range (5):
if i > 2:
break
print (i)
0
1
2

L’instruction continue saute à l’itération suivante, sans exécuter la suite du bloc


d’instructions de la boucle.

>>> for i in range (5):


if i == 2:
continue
print (i)
0
1
3
4

VI. Les collections


1. Les listes
Une liste est une structure de données qui contient une série de valeurs. Python
autorise la construction de liste contenant des valeurs de types différents (par
exemple entier et chaîne de caractères), ce qui leur confère une grande flexibilité. Une
liste est déclarée par une série de valeurs (n’oubliez pas les guillemets, simples ou
doubles, s’il s’agit de chaînes de caractères) séparées par des virgules, et le tout
encadré par des crochets.
Exemple
>>> animaux = [" girafe ", " tigre ", " singe ", " souris "]
>>> tailles = [5, 2.5 , 1.75 , 0.15]
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

>>> mixte = [" girafe ", 5, " souris ", 0.15]


L’accès aux éléments d’une liste se fait par indice.
Exemple
>>> animaux = [" girafe ", " tigre ", " singe ", " souris "]
>>> animaux [0]
'girafe '
>>> animaux [1]
'tigre '
>>> animaux [3]
'souris '
La liste peut également être indexée avec des nombres négatifs. Les indices négatifs
reviennent à compter à partir de la fin. Leur principal avantage est que vous pouvez
accéder au dernier élément d’une liste à l’aide de l’indice -1 sans pour autant
connaître la longueur de cette liste. L’avant-dernier élément a lui l’indice -2, l’avant-
avant dernier l’indice -3, etc.

liste : [" girafe ", " tigre ", " singe ", " souris "]
indice positif : 0 1 2 3
indice négatif : -4 -3 -2 -1

Exemple
>>> animaux = [" girafe ", " tigre ", " singe ", " souris "]
>>> animaux [ -1]
'souris '
>>> animaux [ -2]
'singe '

L’opérateur + est très pratique pour concaténer deux listes. Vous pouvez aussi utiliser
la méthode .append() lorsque vous souhaitez ajouter un seul élément à la fin d’une
liste.
>>> a = []
>>> a = a + [15, 8 ,-10]
>>> a
[15,8,-10]
>>> a. append (13)
>>> a
[15 , 8,- 10,13]
Un autre avantage des listes est la possibilité de sélectionner une partie d’une liste en
utilisant un indexage construit sur le modèle [m:n+1] pour récupérer tous les
éléments, du émième au énième (de l’élément m inclus à l’élément n+1 exclu). On dit
alors qu’on récupère une tranche de la liste, par exemple :
>>> animaux = [" girafe ", " tigre ", " singe ", " souris "]
>>> animaux [0:2]
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

['girafe ', 'tigre ']


>>> animaux [0:]
['girafe ', 'tigre ', 'singe ', 'souris ']
>>> animaux [:]
['girafe ', 'tigre ', 'singe ', 'souris ']
>>> animaux [1:]
['tigre ', 'singe ', 'souris ']
>>> animaux [1: -1]
['tigre ', 'singe ']
On peut aussi préciser le pas en ajoutant un symbole deux-points supplémentaire et
en indiquant le pas par un entier selon le modèle liste[début:fin:pas].
>>> animaux = [" girafe ", " tigre ", " singe ", " souris "]
>>> animaux [0:3:2]
['girafe ', 'singe ']
>>> x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x [::1]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x [::2]
[0, 2, 4, 6, 8]
>>> x [::3]
[0, 3, 6, 9]
>>> x [1:6:3]
[1, 4]

2. Les tuples
Les tuples (« n-uplets » en français) en Python dont des listes non modifiables,
Pratiquement, ils utilisent les parenthèses au lieu des crochets
>>> x = (1, 2, 3)
>>> x
(1, 2, 3)
>>> x [2]
3
>>> x [0:2]
(1, 2)
>>> x [2] = 15
Traceback ( innermost last ):
File "<stdin >", line 1, in ?
TypeError : object doesn 't support item assignment

L’affectation et l’indiçage fonctionnent comme avec les listes. Mais si on essaie de


modifier un des éléments du tuple, Python renvoie un message d’erreur. Si vous
voulez ajouter un élément (ou le modifier), vous devez créer un autre tuple :
>>> x = (1, 2, 3)
>>> x + (2 ,)
(1, 2, 3, 2)
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Pour utiliser un tuple d’un seul élément, vous devez utiliser une syntaxe avec une
virgule (element,), ceci pour éviter une ambiguïté avec une simple expression. Autre
particularité des tuples, il est possible d’en créer de nouveaux sans les parenthèses,
dès lors que ceci ne pose pas d’ambiguïté avec une autre expression :
>>> x = (1, 2, 3)
>>> x
(1, 2, 3)
>>> x = 1, 2, 3
>>> x
(1, 2, 3)
On peut utiliser la fonction tuple(sequence) qui prend en argument un objet
séquentiel et renvoie le tuple correspondant (opération de casting) :
>>> tuple ([1 ,2 ,3])
(1, 2, 3)
>>> tuple (" ATGCCGCGAT ")
('A', 'T', 'G', 'C', 'C', 'G', 'C', 'G', 'A', 'T ')

3. Les dictionnaires
Les dictionnaires sont des collections non ordonnées d’objets, c’est-à-dire qu’il n’y a
pas de notion d’ordre (i.e. pas d’indice). On accède aux valeurs d’un dictionnaire par
des clés.
>>> ani1 = {}
>>> ani1 [" nom "] = " girafe "
>>> ani1 [" taille "] = 5.0
>>> ani1 [" poids "] = 1100
>>> ani1
{'nom ': 'girafe ', 'taille ': 5.0 , 'poids ': 1100}
On peut aussi initialiser toutes les clés et les valeurs d’un dictionnaire en une seule
opération :
>>> ani2 = {" nom ": " singe ", " poids ": 70, " taille ": 1.75}
Mais rien ne nous empêche d’ajouter une clé et une valeur supplémentaire :
>>> ani2 [" age "] = 15
Pour récupérer la valeur associée à une clé donnée, il suffit d’utiliser la syntaxe
suivante dictionnaire ["cle"]. Par exemple :
>>> ani1 [" taille "]
5.0
Il est possible d’obtenir toutes les valeurs d’un dictionnaire à partir de ses clés :
>>> for key in ani2 :
print (key , ani2 [ key ])

nom singe
poids 70
taille 1.75
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

age 15
Les méthodes .keys() et .values() renvoient, comme vous pouvez vous en doutez, les
clés et les valeurs d’un dictionnaire:
>>> print(ani2.keys())
dict_keys([' nom ', ' poids ', ' taille ', ' age '])
>>> print(ani2.values ())
dict_values([' singe ', 70, 1.75, 15])

Les mentions dict_keys et dict_values indiquent que nous avons à faire à des objets
un peu particuliers. Ils ne sont pas indexables (on ne peut pas retrouver un élément
par indice, par exemple dico.keys()[0] renverra une erreur). Si besoin, nous pouvons
les transformer en liste avec la fonction list() :
>>> ani2 . values ()
dict_values ([' singe ', 70, 1.75])
>>> list ( ani2 . values ())
['singe ', 70, 1.75]

Quelques méthodes utiles : dict, get, sorted, min, max,…

4. Les sets
Les containers de type set représentent un autre type d’objet séquentiel qui peut se
révéler très pratique. Ils ont la particularité d’être non modifiables, non ordonnés et
de ne contenir qu’une seule copie maximum de chaque élément. Pour créer un
nouveau set on peut utiliser les accolades :
>>> s = {1, 2, 3, 3}
>>> s
{1, 2, 3}
>>> type (s)
<class 'set '>
En général, on utilisera la fonction interne à Python set() pour générer un nouveau
set. Celle-ci prend en argument n’importe quel objet itérable et le convertit en set
(opération de casting) :
>>> set ([1 , 2, 4, 1])
{1, 2, 4}
>>> set ((2 , 2, 2, 1))
{1, 2}
>>> set ( range (5))
{0, 1, 2, 3, 4}
>>> set ({" clé 1": 1, "clé 2": 2})
{'clé1', 'clé2'}
>>> set ([" ti", "to", "to "])
{'ti ', 'to '}
>>> set (" Maître corbeau sur un arbre perch é")
{'h', 't', 'M', 'e', 'b', 'u', 'n', 'r', 'c', 'o', 's', ' ', 'p', 'é', 'î', 'a'}
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Nous avons dit plus haut que les sets ne sont pas ordonnés, il est donc impossible de
récupérer un élément par sa position. Il est également impossible de modifier un de
ses éléments. Par contre, les sets sont itérables :
>>> s = set ([1 , 2, 4, 1])
>>> s [1]
Traceback ( most recent call last ):
File "<stdin >", line 1, in <module >
TypeError : 'set ' object is not subscriptable
>>> for elt in s:
print (elt)
1
2
4
Les containers de type set sont très utiles pour rechercher les éléments uniques d’une
suite d’éléments. Cela revient à éliminer tous les doublons.
On peut bien sûr transformer dans l’autre sens un set en liste. Cela permet par
exemple d’éliminer les doublons de la liste initiale tout en récupérant une liste à la
fin:
>>> list ( set ([7 , 9, 6, 6, 7, 3, 8, 5, 6, 7]))
[3, 5, 6, 7, 8, 9]
On peut faire des choses très puissantes. Par exemple, un compteur de lettres en
combinaison avec une liste de compréhension, le tout en une ligne !
>>> seq = " atctcgatcgatcgcgctagctagctcgccatacgtacgactacgt "
>>> set ( seq )
{'c', 'g', 't', 'a '}
>>> [( base , seq . count ( base )) for base in set ( seq )]
[('c', 15) , ('g', 10) , ('t', 11) , ('a', 10)]
Les sets permettent aussi l’évaluation d’union ou d’intersection mathématiques en
conjonction avec les opérateurs respectivement | et & :
>>> l = [3, 3, 5, 1, 3, 4, 1, 1, 4, 4]
>>> l2 = [3, 0, 5, 3, 3, 1, 1, 1, 2, 2]
>>> set (l) & set(l2)
{1, 3, 5}
>>> set (l) | set(l2)
{0, 1, 2, 3, 4, 5}

Remarque :
Les listes, les dictionnaires et les tuples sont des objets qui peuvent contenir des
collections d’autres objets. On peut donc construire des listes qui contiennent des
dictionnaires, des tuples ou d’autres listes, mais aussi des dictionnaires contenant des
tuples, des listes, etc.
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

VII. Les modules


Les modules sont des bibliothèques Python qui contiennent des fonctions prédéfinies
que l’on est amené à réutiliser souvent. Ce sont des « boîtes à outils » qui vont vous
être très utiles, ces module sont organisé par thème.
La syntaxe import nomModule permet d’importer la série de fonctions existantes
dans le module nomModule. Par exemple, les fonctions qui gère les nombres
aléatoires existe dans le module random et les fonctions mathématiques dans math.

>>> import math


>>> math. cos ( math.pi / 2)
6.123233995736766 e -17
>>> math. sin ( math.pi / 2)
1.0

Python possède de nombreux autres modules internes, voici une liste non
exhaustive :
- asyncio : thread, socket, protocol.
- calendar : gérer les calendriers, les dates.
- cmath : fonctions mathématiques complexes.
- collections : structures de données supplémentaires pour les séquences et les
dictionnaires
- copy : copies d’instances de classes.
- datetime : calculs sur les dates et heures
- math : fonctions mathématiques standard telles que cos, exp, log…
- os : fonctions élémentaires pour interagir avec le système d’exploitation
- pathlib : manipulation de chemins.
- random : génération de nombres aléatoires
- string : manipulations des chaînes de caractères
- time : accès à l’heure, l’heure système, l’heure d’un fichier
- tkinter : interface graphique
- unittest : Tests unitaires

Les principaux modules utilisés en intelligence artificielle et machine learning sont :

- TensorFlow : est une bibliothèque python complète d'apprentissage


automatique permettant d'effectuer des calculs numériques de haut niveau.
- Keras : est une bibliothèque Python conçue pour construire des réseaux
neuronaux et des projets d'apprentissage automatique.
- NumPy : contient des fonctions permettant de traiter des opérations
mathématiques complexes telles que l'algèbre linéaire, la transformation de
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Fourier, les nombres aléatoires et des fonctions permettant de travailler avec


des matrices et des tableaux n en Python.
- Python Pandas : est une bibliothèque open-source qui offre un large éventail
d'outils pour la manipulation et l'analyse des données.
- Seaborn Python : offre une interface de haut niveau basée sur des ensembles
de données pour créer des graphiques statistiques.

Il existe un autre moyen d’importer une ou plusieurs fonctions d’un module, À l’aide
du mot-clé from, on peut importer une fonction spécifique d’un module donné

>>>from random import randint # importe la fonction randint du module random


>>> randint (0 ,50)
46
>>>from random import * # importe toutes fonctions du module random
>>> uniform (0 ,2.5)
0.64943174760727951

Pour vider de la mémoire un module déjà chargé, on peut utiliser l’instruction del
>>> import random
>>> random . randint (0 ,10)
2
>>> del random
>>> random . randint (0 ,10)
Traceback ( most recent call last ):
File "<stdin >", line 1, in ?
NameError : name 'random ' is not defined

Il est possible de donner un alias à un module comme dans l’exemple suivant :


>>> import numpy as np

Il est aussi possible de donner un alias à une fonction selon la syntaxe suivante :
>>>from nomModule import nomfonct as aliasFont

VIII. Les fonctions


Pour définir une fonction, Python utilise le mot-clé def. Si on souhaite que la fonction
renvoie quelque chose, il faut utiliser le mot-clé return. Par exemple :
>>> def carre (x):
return x **2

>>> print ( carre (2))


4
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Une fonction ne prend pas forcément un argument et ne renvoie pas forcément une
valeur. Le nombre d’arguments que l’on peut passer à une fonction est variable et il
n’est pas obligatoire de préciser le type des arguments que vous lui passez.
En Python, les fonctions sont capables de renvoyer plusieurs objets à la fois

>>> def carre_cube (x):


return x**2 , x **3

>>> carre_cube (2)


(4, 8)

Ou bien

>>> def carre_cube2 (x):


return [x**2 , x **3]

>>> carre_cube2 (3)


[9, 27]

L’affectation multiple est très pratique dans ce cas :


>>> z1 , z2 = carre_cube2 (3)
>>> z1
9
>>> z2
27

Il est strictement obligatoire de préciser le même nombre d’argument et de respecter


le même ordre lors de l’appel que dans la définition de la fonction. Mais il est aussi
possible de passer un ou plusieurs argument(s) de manière facultative et de leur
attribuer une valeur par défaut :

>>> def fct (x =1):


return x

>>> fct ()
1
>>> fct (10)
10

Un argument défini avec une syntaxe def fct(arg=val) : est appelé argument par
mot-clé. Le passage d’un tel argument lors de l’appel de la fonction est facultatif. Ce
type d’argument ne doit pas être confondu avec les arguments positionnels présentés
ci-dessus, dont la syntaxe est def fct(arg):.
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Il est bien sûr possible de passer plusieurs arguments par mot-clé :


>>> def fct (x=0, y=0, z =0):
return x, y, z

>>> fct ()
(0, 0, 0)
>>> fct (10)
(10 , 0, 0)
>>> fct (10 , 8)
(10 , 8, 0)
>>> fct (10 , 8, 3)
(10 , 8, 3)

Si on souhaitait préciser l’argument par mot-clé z et garder les valeurs de x et y par


défaut, il faut simplement préciser le nom de l’argument lors de l’appel :

>>> fct (z =10)


(0, 0, 10)

Python permet même de rentrer les arguments par mot-clé dans un ordre arbitraire :
>>> fct (z=10 , x=3, y =80)
(3, 80, 10)
>>> fct (z=10 , y =80)
(0, 80, 10)

Lorsque nous avons un mélange d’arguments positionnels et par mot-clé, les


arguments positionnels doivent toujours être placés avant les arguments par mot-clé
>>> def fct (a, b, x=0, y=0, z =0):
return a, b, x, y, z
>>> fct (1, 1)
(1, 1, 0, 0, 0)
>>> fct (1, 1, z =5)
(1, 1, 0, 0, 5)
>>> fct (1, 1, z=5, y =32)
(1, 1, 0, 32, 5)
On peut toujours passer les arguments par mot-clé dans un ordre arbitraire à partir
du moment où on précise leur nom. Par contre, si les deux arguments positionnels a
et b ne sont pas passés à la fonction, Python renvoie une erreur.
Les variables créées au sein d’une fonction sont locales et donc ne sont pas visibles à
l’extérieur de celle-ci.
Lorsqu’une variable est déclarée dans le programme principal, elle est visible dans
celui-ci ainsi que dans toutes les fonctions, on parle de variable globale. Python ne
permet pas la modification d’une variable globale dans une fonction mais si on veut
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

vraiment modifier une variable globale dans une fonction, il faut utiliser le mot-clé
global :
>>> def ma_fonction ():
global x
x=x+1
>>> x = 1
>>> ma_fonction ()
>>> x
2
Attention : si vous passez une liste en argument, elle est modifiable au
sein de la fonction
>>> def ma_fonction (x):
x[1] = -15
>>> y = [1 ,2 ,3]
>>> ma_fonction (y)
>>> y
[1, -15, 3]

IX. Tableaux et calcul matriciel avec NumPy


Nous utilisons une importation de NumPy et l’attribution d’un alias np :
import numpy as np

Pour créer un tableau 1D, il suffit de passer une liste de nombres en argument à la
fonction numpy.array(). Une liste est constituée de nombres séparés par des virgules
et entourés de crochets
>>>a = np.array([4,7,9])
>>>a
array([4, 7, 9])

Pour créer un tableau 2D, il faut transmettre à numpy.array() une liste de listes
grâce à des crochets imbriqués.
>>>a = np.array([[1, 2, 3], [4, 5, 6]])
>>>a
array([[1, 2, 3],
[4, 5, 6]])

La fonction numpy.size() renvoie le nombre d’éléments du tableau.


>>>a = np.array([2,5,6,8])
>>>np.size(a)
4
>>>b = np.array([[1, 2, 3],
[4, 5, 6]])
>>>np.size(b)
6
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

La fonction numpy.shape() renvoie la taille du tableau.


>>>a = np.array([2,5,6,8])
>>>np.shape(a)
(4,)
>>>b = np.array([[1, 2, 3],
[4, 5, 6]])
>>>np.shape(b)
(2, 3)

Les opérateurs +, -, *, / permettent d’effectuer respectivement l’addition, la


soustraction, le produit et la division terme à terme. Il faut dans ce cas que les deux
tableaux aient la même taille. Ces opérateurs peuvent aussi être utilisés entre un
scalaire et un tableau, l’opération sera appliquée à tous les éléments du tableau avec
ce scalaire.
>>>a = np.array([[1, 2, 3],
[4, 5, 6]])
>>>b = np.array([[2, 1, 3],
[3, 2, 1]])
>>>a*b
array([[ 2, 2, 9],
[12, 10, 6]])
Il est également possible d’élever chaque nombre d’un tableau à une puissance
donnée :
>>>t_1 = np.array([1,2,3,4])
>>>print("t_1 ** 3 : \n", t_1 ** 3)
t_1 ** 3 :
[ 1 8 27 64]

la fonction numpy.dot() permet de réaliser le produit matriciel.


>>>a = np.array([[1, 2, 3],
[4, 5, 6]])
>>>b = np.array([[4],
[2],
[1]])
>>>np.dot(a,b)
array([[11],
[32]])

Pour extraire une tranche d’un tableau, on peut utiliser l’opérateur « : » avec la
syntaxe suivante : nomTableau[indDeb:indFin:pas]
>>>a = np.array([12, 25, 34, 56, 87])
>>>a[1:3]
array([25, 34])
Il est aussi possible de ne pas mettre de début ou de fin.
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

>>>a[1:]
array([25, 34, 56, 87])
>>>a[:3]
array([12, 25, 34])
>>>a[:]
array([12, 25, 34, 56, 87])
L’extraction de partie est valable aussi pour les tableaux 2D
>>>a = np.array([[1, 2, 3],
[4, 5, 6]])
>>>a[0,1]
2
>>>a[:,1:3]
array([[2, 3],
[5, 6]])
>>>a[:,1]
array([2, 5])
>>>a[0,:]
array([1, 2, 3])

a[:,n] donne un tableau 1D correspondant à la colonne d’indice n de a. Si on veut


obtenir un tableau 2D correspondant à la colonne d’indice n, il faut faire du slicing en
utilisant a[:,n:n+1].
>>>a[:,1:2]
array([[2],
[5]])

La fonction numpy. arange() permet de générer une séquence de nombres séparés


par un intervalle fixe, le tout stocké dans un tableau
>>>print( np.arange(5) )
[0 1 2 3 4]
>>>print( np.arange(2, 5) )
[2 3 4]
>>>print( np.arange(2, 10, 2) )
[2 4 6 8]

La fonction numpy.append() permet de rajouter des élément au tableau. Il faut


noter que l’appel à cette fonction ne modifie pas l’objet auquel on ajoute les valeurs.
Si on désire que les modifications sont apportées à cet objet, il faut l’écraser
>>>t_1 = np.array([1,3,5])
>>>print("t_1 : ", t_1)
t_1 : [1 3 5]
>>>t_1 = np.append(t_1, 1)
>>>print("t_1 après l'ajout : ", t_1)
t_1 après l'ajout : [1 3 5 1]
Pour ajouter une colonne à un tableau à deux dimensions :
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

>>>t_2 = np.array([[1,2,3], [5,6,7]])


>>>print("t_2 : \n", t_2)
t_2 :
[[1 2 3]
[5 6 7]]
>>>ajout_col_t_2 = np.array([[4], [8]])
>>>t_2 = np.append(t_2,ajout_col_t_2, axis = 1)
>>>print("t_2 après ajout colonne : \n", t_2)
t_2 après ajout colonne :
[[1 2 3 4]
[5 6 7 8]]
Pour ajouter une ligne, on utilise la fonction vstack() de Numpy :
>>>ajout_ligne_t_2 = np.array([10, 11, 12, 13])
>>>t_2 = np.vstack([t_2,ajout_ligne_t_2])
>>>print("t_2 après ajout ligne : \n", t_2)
t_2 après ajout ligne :
[[ 1 2 3 4]
[ 5 6 7 8]
[10 11 12 13]]

Pour supprimer des éléments, on utilise la fonction delete() de NumPy :


>>>print("t_1 : ", t_1)
t_1 : [1 3 5 1]
# Supprimer le dernier élément
>>>t_1 = np.delete(t_1, (-1))

Pour supprimer plusieurs éléments :


>>>print("t_1 : ", t_1)
# Supprimer les 1er et 3e éléments
>>>t_1 = np.delete(t_1, ([0, 2]))
>>>print(t_1)
[3 1]

Pour supprimer une colonne d’un tableau à deux dimensions :


>>>print("t_2 : ", t_2)
t_2 : [[ 1 2 3 4]
[ 5 6 7 8]
[10 11 12 13]]
# Supprimer la première colonne :
>>>np.delete(t_2, (0), axis=1)

Supprimer plusieurs colonnes :


>>>print("t_2 : ", t_2)
t_2 : [[ 1 2 3 4]
[ 5 6 7 8]
[10 11 12 13]]
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

# Supprimer la 1ère et la 3e colonne :


>>>np.delete(t_2, ([0,2]), axis=1)

Et pour supprimer une ligne :


>>>print("t_2 : ", t_2)
t_2 : [[ 1 2 3 4]
[ 5 6 7 8]
[10 11 12 13]]

# Supprimer la première ligne :


np.delete(t_2, (0), axis=0)

Supprimer plusieurs lignes :


>>>print("t_2 : ", t_2)
#Supprimer la 1ère et la 3e ligne
t_2 : [[ 1 2 3 4]
[ 5 6 7 8]
[10 11 12 13]]
>>>np.delete(t_2, ([0,2]), axis=0)

NumPy fournit de nombreuses méthodes pour calculer des statistiques sur l’ensemble
des valeurs des tableaux, ou sur un des axes des tableaux (par exemple sur
l’équivalent de lignes ou des colonnes dans les tableaux à deux dimensions).
Fonction Description
sum(), nansum() Retourne la somme des éléments (nansum(x) ne tient pas
compte des valeurs NaN)
prod() Retourne le produit des éléments
cumsum() Retourne la somme cumulée des éléments
cumprod() Retourne le produit cumulé des éléments
mean(),nanmean() Retourne la moyenne
var(),nanvar() Retourne la variance
std(),nanstd() Retourne l’écart-type
min(), nanmin() Retourne la valeur minimale
max(),nanmax() Retourne la valeur maximale
argmin() Retourne l’indice du premier élément à la plus petite valeur
argmax() Retourne l’indice du premier élément à la plus grande valeur

La génération de nombres pseudo-aléatoires est permise par le module random de


Numpy
Fonction Description
rand(size) Tirage de size valeurs selon une Uniforme [0, 1]
uniform(a,b,size) Tirage de size valeurs selon une Uniforme [a; b]
randint(a,b,size) Tirage de size valeurs selon une Uniforme [a; b[
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

randn(size) Tirage de size valeurs selon une Normale centrée réduite


normal(mu, std, size) Tirage de size valeurs selon une Normale d’espérance
mu etd’écart-type std
binomial(size) Tirage de size valeurs selon une Bin(n, p)
poisson(lambda, size) Tirage de size valeurs selon une loi de Poisson de
paramètre lambda

Autres fonctions :
- numpy.zeros() : zeros(n) renvoie un tableau 1D de n zéros et zeros((m,n)) renvoie
tableau 2D de taille m x n de 0.
- numpy.ones() : ones(n) renvoie un tableau 1D rempli par des 1 et ones((m,n))
renvoie tableau 2D de taille m x n rempli de 1.
- numpy.eye() : eye(n) renvoie tableau 2D carré de taille n x n, avec des uns sur la
diagonale et des zéros partout ailleurs
- numyp.diag() : prend en paramètre une liste et crée une matrice avec sur la
diagonale la liste donnée.
- numyp. Identity() : crée la matrice identité
- nomTab. copy() : permet de copier le tableau dans un autre
- numpy.sort() : permet de trier un tableau passé en paramètre
- numpy.transpose() : permet de transposé une matrice

X. Visualisation des données


Nous allons explorer dans cette section les essentiels de la visualisation de données
avec la librairie Matplotlib. Pour utiliser les fonctionnalités offertes par cette librairie,
il est nécessaire de charger certains modules. Le plus commun est le sous-module
pyplot, auquel on attribue fréquemment l’alias plt :

import matplotlib.pyplot as plt

1. Courbes/lignes
Pour tracer des lignes sur un repère cartésien, on utilise la fonction plot(), à qui on
fournit les coordonnées en abscisses et en ordonnées en premiers paramètres. On
définit avec le troisième paramètre la géométrie

>>>x = np.arange(-10, 11)


>>>y = x**2
>>>plt.plot(x, y)
>>>y_2 = -x**2
>>>plt.plot(x, y_2, color="red")
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

On peut également spécifier un marqueur à chaque point sur la courbe :


>>>plt.plot(x, y, "o")

Pour contrôler de manière plus précise les marqueurs, on peut utiliser les paramètres
suivants :
- marker : renseigne le type de marqueur (. o v < > * | h p D x +…)
- markerfacecolor : la couleur désirée pour les marqueurs ;
- markersize : taille des marqueurs.
-
>>>plt.plot(x, y, marker="o", markerfacecolor = "red", markersize = 10)

2. Nuage de points
Pour en réaliser un graphique de type nuage de points, on peut faire appel à la
fonction scatter(), à qui l’on indique les cordonnées (x,y) des points ainsi que
quelques paramètres optionnels de forme ou d’esthétisme. Pour changer la forme des
marqueurs, on l’indique via le paramètre marker, la taille des points est ajustable
via le paramètre s, tandis que la couleur se modifie via le
paramètre color (on peut associer une couleur et une taille spécifiques à chaque
point)

>>>x = np.random.rand(30)
>>>y = np.random.rand(30)
>>>z = np.random.rand(30)
>>>couleurs = np.random.choice(["blue", "black", "red"], 30)
>>>plt.scatter(x, y, marker="o", color = couleurs, s = z*100)
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

3. Histogramme
Pour réaliser un histogramme avec pyplot, on utilise la fonction hist() :
>>>x = np.random.randn(1000)
>>>plt.hist(x)

On peut préciser avec le paramètre bins soit le nombre de classes, soit leurs bornes :
>>>plt.hist(x, bins=30)
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

XI. Manipulation des données avec pandas


pandas est une librairie open-source basée sur NumPy fournissant des structures de
données facile à manipuler, et des outils d’analyse de données. Pour avoir accès aux
fonctionnalités de pandas, il est coutume de charger la librairie en lui accordant
l’alias pd :
import pandas as pd

1. Structures
Nous allons nous pencher sur deux types de structures, les séries (serie) et les
dataframes (DataFrame).

a. Les séries
Les séries sont des tableaux à une dimension de données indexées. Pour en créer, on
peut définir une liste, puis appliquer la fonction Series de pandas :
>>>s = pd.Series([1, 4, -1, np.nan, .5, 1])
>>>print(s)

0 1.0
1 4.0
2 -1.0
3 NaN
4 0.5
5 1.0
dtype: float64

L’attribut values permet d’afficher les valeurs qui sont stockées dans un tableau
numpy et Les indices sont stockés dans une structure spécifique de pandas

>>>print("index de s : ", s.index)


>>>print("valeur de s : ", s.values)

index de s : RangeIndex(start=0, stop=6, step=1)


valeur de s : [ 1. 4. -1. nan 0.5 1. ]

Il est possible d’attribuer un nom à la série ainsi qu’à l’index :

>>>s.name = "ma_serie"
>>>s.index.name = "nom_index"
>>>print("nom de la série : {} , nom de l'index : {}".format(s.name, s.index.name))
nom de la série : ma_serie , nom de l'index : nom_index
L’index peut être défini par l’utilisateur, au moment de la création de la série :
>>>s = pd.Series([1, 4, -1, np.nan],
>>>index = ["o", "d", "i", "l"])
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

>>>print(s)
o 1.0
d 4.0
i -1.0
l NaN
dtype: float64
On peut définir l’indice avec des valeurs numériques également, sans être forcé de
respecter un ordre précis :
>>>s = pd.Series([1, 4, -1, np.nan],
>>>index = [4, 40, 2, 3])
>>>print(s)
4 1.0
40 4.0
2 -1.0
3 NaN
dtype : float64
L’index peut être modifié par la suite, en venant écraser l’attribut index :
>>>s.index = ["o", "d", "i", "l"]
>>>print("Série s : \n", s)
Série s :
o 1.0
d 4.0
i -1.0
l NaN
dtype : float64
Pour créer des séries avec une valeur répétée, il suffit de fournir un scalaire à la
fonction Series de NumPy et un index dont la longueur correspondra au nombre de
fois où le scalaire sera répété :
>>>s = pd.Series(5, index = [np.arange(4)])
>>>print(s)
05
15
25
35
dtype : int64
On peut créer une série à partir d’un dictionnaire :
>>>dictionnaire = {"Roi": "Arthur",
"Chevalier_pays_galles": "Perceval",
"Druide": "Merlin"}
>>>s = pd.Series(dictionnaire)
>>>print(s)
Roi Arthur
Chevalier_pays_galles Perceval
Druide Merlin
dtype : object
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Les clés du dictionnaire ont été utilisées pour l’index. Lors de la création de la série,
on peut préciser au paramètre clé des valeurs spécifiques : cela aura pour
conséquence de ne récupérer que les observations correspondant à ces clés :
>>>s = pd.Series(dictionnaire, index = ["Roi", "Druide"])
>>>print(s)
Roi Arthur
Druide Merlin
dtype: object

b. Les dataframes
Les Dataframes correspondent au format de données que l’on rencontre
classiquement en économie, des tableaux à deux dimensions, avec des variables en
colonnes et des observations en ligne. Les colonnes et lignes des dataframes sont
indexées. Pour créer un dataframe, on peut fournir à la fonction DataFrame() de
pandas un dictionnaire pouvant être transformé en serie. C’est le cas d’un
dictionnaire dont les valeurs associées aux clés ont toutes la même longueur :
>>>dico = {"height" :[58, 59, 60, 61, 62,63, 64, 65, 66, 67,68, 69, 70, 71, 72],
"weight":[115, 117, 120, 123, 126,129, 132, 135, 139, 142,146, 150, 154, 159, 164]}
>>>df = pd.DataFrame(dico)
>>>print(df)
height weight
0 58 115
1 59 117
2 60 120
3 61 123
4 62 126
5 63 129
6 64 132
7 65 135
8 66 139
9 67 142
10 68 146
11 69 150
12 70 154
13 71 159
14 72 164

La position des éléments dans le dataframe sert d’index. Comme pour les séries, les
valeur sont accessibles dans l’attribut values et l’index dans l’attribut index. Les
colonnes sont également indexées :
>>>print(df.columns)
Index ([' height ', 'weight '], dtype =' object ')
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

La méthode head() permet d’afficher les premières lignes (les 5 premières, par
défaut). On peut modifier son paramètre n pour indiquer le nombre de lignes à
retourner :
>>>df.head(2)

Lors de la création d’un dataframe à partir d’un dictionnaire, si on précise le nom des
colonnes à importer par une liste de chaînes de caractères fournie au paramètree
columns de la fonction DataFrame, on peut non seulement définir les colonnes à
remplir mais également leur ordre d’apparition. Par exemple, pour n’importer que la
colonne weight :
>>>df = pd.DataFrame(dico, columns = ["weight"])
>>>print(df.head(2))
weight
0 115
1 117
Et pour définir l’ordre dans lequel les colonnes apparaîtront :
>>>df = pd.DataFrame(dico, columns = ["weight", "height"])
>>>print(df.head(2))
weight height
0 115 58
1 117 59
Si on indique un nom de colonne absent parmi les clés du dictionnaire, le dataframe
résultant contiendra une colonne portant ce nom mais remplie de valeurs NaN :
>>>df = pd.DataFrame(dico, columns = ["weight", "height", "age"])
>>>print(df.head(2))
weight height age
0 115 58 NaN
1 117 59 NaN

Un dataframe peut être auusi créé à partir d’une série :


>>>s = pd.Series([1, 4, -1, np.nan], index = ["o", "d", "i", "l"])
>>>s.name = "nom_variable"
>>>df = pd.DataFrame(s, columns = ["nom_variable"])
>>>print(df)
nom_variable
o 1.0
d 4.0
i -1.0
l NaN
Si on n’attribue pas de nom à la série, il suffit de ne pas renseigner le paramètre
columns de la fonction DataFrame. Mais dans ce cas, la colonne n’aura pas de non,
juste un index numérique.
>>>s = pd.Series([1, 4, -1, np.nan], index = ["o", "d", "i", "l"])
>>>df = pd.DataFrame(s)
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

>>>print(df)
0
o 1.0
d 4.0
i -1.0
l NaN
Un dataframe peut être créé à partir d’une liste de dictionnaires :
>>>dico_1 = {
"Nom": "Pendragon",
"Prenom": "Arthur",
"Role": "Roi de Bretagne"
}
>>>dico_2 = {
"Nom": "de Galles",
"Prenom": "Perceval",
"Role": "Chevalier du Pays de Galles"
}
>>>df = pd.DataFrame([dico_1, dico_2])
>>>print(df)
Nom Prenom Role
0 Pendragon Arthur Roi de Bretagne
1 de Galles Perceval Chevalier du Pays de Galles
On peut aussi créer un dataframe à partir d’un tableau Numpy. Lors de la création,
avec la fonction DataFrame() de NumPy, il est possible de préciser le nom des
colonnes (à défaut, l’indiçage des colonnes sera numérique)
>>>tableau = [[1, 2, 3],[11, 22, 33],[111, 222, 333],[1111, 2222, 3333]]
>>>tableau_np = np.array(tableau)
>>>df=pd.DataFrame(tableau_np,columns = ["a", "b", "c"])
>>>print(df)
a b c
0 1 2 3
1 11 22 33
2 111 222 333
3 1111 2222 3333

- Dimensions d’un dataframe: df.shape


- Nombre de lignes comme suit : len(df)
- Nombre de colonnes : len(df.columns)
- Modification des indices des lignes : df.index = [liste des indices séparés
par ,]
- Modification des indices des colonnes : df.columns = liste des indices
séparés par ,]
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

2. Sélection des données


Dans cette section, nous regardons différentes manières de sélectionner des données
dans des séries et dataframes. On note deux manières bien distinctes :
- une première basée sur l’utilisation de crochets directement sur l’objet pour
lequel on souhaite sélectionner certaines parties ;
- seconde s’appuyant sur des indexeurs, accessibles en tant qu’attributs d’objets
NumPy (loc, at, iat, etc.), cette méthode permet d’éviter certaines confusions
qui peuvent apparaître dans le cas d’index numériques.

a. Sélection dans les séries


On peut utiliser l’index pour extraire les données :
>>>s = pd.Series([1, 4, -1, np.nan, .5, 1])
>>>s[0] # 1er élément de s
>>>s[1:3] # du 2e élément (inclus) au 4e (non inclus)
>>>s[[0,4]] # 1er et 5e éléments
On note que contrairement aux tableaux numpy ou aux listes, on ne peut pas utiliser
des valeurs négatives pour l’index afin de récupérer les données en comptant leur
position par rapport à la fin.
Dans le cas d’un indice composé de chaînes de caractères, il est alors possible, pour
extraire les données de la série, de faire référence soit au contenu de l’indice (pour
faire simple, son nom), soit à sa position :
>>>s = pd.Series([1, 4, -1, np.nan],
>>>index = ["o", "d", "i", "l"])
>>>print("La série s : \n", s)
La série s :
o 1.0
d 4.0
i -1.0
l NaN
dtype : float64
>>>print('s["d"] : \n', s["d"]) # ou print('s[1] : \n', s[1])
s["d"] :
4.0
>>>print("éléments o et i : \n", s[["o", "i"]])
éléments o et i :
o 1.0
i -1.0
dtype : float64

Par contre, dans le cas où l’indice est défini avec des valeurs numériques, pour
extraire les valeurs à l’aide des crochets, ce sera par la valeur de l’indice et pas en
s’appuyant sur la position :
>>>s = pd.Series([1, 4, -1, np.nan], index = [4, 40, 2, 3])
>>>print(s[40])
4.0
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Pour la deuxième manière de sélection dans les série, pandas propose deux types
d’indexage multi-axes : loc, iloc. Le premier est principalement basé sur l’utilisation
des labels des axes, tandis que le second s’appuie principalement sur les positions à
l’aide d’entiers.

Créons tout d’abord deux séries ; une première avec un index textuel, une deuxième
avec un index numérique :
>>>s_num = pd.Series([1, 4, -1, np.nan], index = [5, 0, 4, 1])
>>>s_texte = pd.Series([1, 4, -1, np.nan], index = ["c", "a", "b", "d"])

Pour extraire un objet avec loc, on utilise le nom de l’indice :


>>>print(s_num.loc[5], s_texte.loc["a"])
1.0 4.0

Pour extraire un élément unique avec iloc, il suffit d’indiquer sa position :


>>>print(s_num.iloc[2], s_texte.iloc[1])
-1.0 4.0

Pour extraire plusieurs éléments avec loc, on utilise les noms (labels) des indices, que
l’on fournit dans une liste :
>>>print("éléments aux labels 5 et 4 :\n", s_num.loc[[5,4]])
éléments aux labels 5 et 4 :
5 1.0
4 -1.0
dtype: float64

>>>print("éléments aux labels c et b : \n", s_texte. loc[["a", "b","c"]])


éléments aux labels c et b :
a 4.0
b -1.0
c 1.0
dtype: float64
Pour extraire plusieurs éléments avec iloc : Exemple s_num.iloc[[0,2]]
On peut effectuer des découpages de séries, pour récupérer des éléments consécutifs :
>>>print("éléments des labels 5 jusqu'à 4 :\n", s_num.loc[5:4])
éléments des labels 5 jusqu'à 4 :
5 1.0
0 4.0
4 -1.0
dtype: float64
Pareil pour l’indexage en texte, on peut extraire en précisant les extrémités : Exemple
s_texte.loc["c":"b"]

Pour extraire plusieurs éléments avec iloc :


>>>print("éléments aux positions de 0 à 2 :\n", s_num.iloc[0:2])
éléments aux positions de 0 à 2 :
5 1.0
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

0 4.0
dtype: float64
>>>print("éléments aux positions de 0 à 2 : \n", s_texte.iloc[0:2])
éléments aux positions de 0 à 2 :
c 1.0
a 4.0
dtype: float64

On peut aussi utiliser un masque pour extraire des éléments, indifféremment en


utilisant loc ou iloc :
>>>print("\n",s_num.loc[[True, False, False, True]])
5 1.0
1 NaN
dtype: float64

b. Sélection dans les dataframes


Lorsqu’on veut effectuer une extraction avec les attributs iloc, la syntaxe est la
suivante : df.iloc[selection_lignes, selection_colonnes]
avec selection_lignes :
— une valeur unique : 1 (seconde ligne) ;
— une liste de valeurs : [2, 1, 3] (3e ligne, 2e ligne et 4e ligne) ;
— un découpage : [2:4] (de la 3e ligne à la 4e ligne (non incluse)).
pour selection_colonnes :
— une valeur unique : 1 (seconde colonne) ;
— une liste de valeurs : [2, 1, 3] (3e colonne, 2e colonne et 4e colonne) ;
— un découpage : [2:4] (de la 3e colonne à la 4e colonne (non incluse)).

Avec loc, la syntaxe est la suivante : df.loc[selection_lignes, selection_colonnes]


avec selection_lignes :
— une valeur unique : "a" (ligne nommée a) ;
— une liste de noms : ["a", "c", "b"] (lignes nommées “a”, “c” et “b”) ;
— un masque : df.['a']<10 (lignes pour lesquelles les valeurs du masque valent True).
Exemple :
>>>masque = df["age"] < 30
>>>print(df.loc[masque])
On peut aussi utiliser la méthode query :
>>>print(df.query("age<30"))
pour selection_colonnes :
— une valeur unique : "a" (colonne nommée a) ;
— une liste de valeurs : ["a", "c", "b"] (colonnes nommées “a”, “c” et “b”) ;
— un découpage : ["a":"c"] (de la colonne nommée “a” à la colonne nommée “c”).
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Autres méthodes utiles :


- Test d’appartenance : pour créer un masque indiquant si les valeurs d’une
série ou d’un dataframe appartiennent à un ensemble, on peut utiliser la
méthode isin()
Exemple : df.height.isin(np.arange(59,61))
- Valeurs manquantes : il est assez fréquent de récupérer des données
incomplètes. La manière dont les données manquantes sont gérées par pandas
est le recours aux deux valeurs spéciales : None pour les objets et NaN pour les
réelles.
o la méthode isnull() renvoie un masque de booléens indiquant True
pour les observations dont la valeur est NaN ou None (s.isnull()),Pour
savoir si une valeur n’est pas nulle, on dispose de la méthode
notnull().
o La méthode dropna() permet quant à elle de retirer les observations
disposant de valeurs nulles.
o La méthode fillna() permet de remplacer les valeurs manquantes par
d’autres valeurs (df.fillna(-9999))
- Suppression : Pour supprimer une valeur sur un des axes d’une série ou d’un
dataframe, NumPy propose la méthode drop().
o Pour les séries, cette méthode prend comme paramètre l’indice
(numérique ou textuel) de la colonne à supprimer. Pour supprimer
plusieurs éléments, il suffit de fournir plusieurs noms d’indice dans une
liste
o Pour les dataframes, on peut supprimer une ou plusieurs lignes en
passant leurs noms à la méthode drop. Pour supprimer une colonne
d’un dataframe, on procède de la même manière que pour les lignes,
mais en ajoutant le paramètre axis=1 à la méthode drop() pour
préciser que l’on s’intéresse aux colonnes
Exemple: df.drop("height", axis=1).

- Ajout d’une valeurs : la méthode append() permet d’ajouter des lignes à la


série ou au dataframe.
- Statistiques : pandas propose quelques méthodes pour effectuer des
statistiques descriptives pour chaque colonne ou par ligne. Pour cela, la
syntaxe est la suivante (tous les paramètres ont une valeur par défaut, la liste
est simplifiée ici) : dataframe.fonction_stat(axis, skipna)
o axis : 0 pour les lignes, 1 pour les colonnes ;
o skipna : si True, exclue les valeurs manquantes pour effectuer les
calculs.
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Parmi les méthodes disponibles : - mean() : moyenne ; - mode() : mode ; -


median() : médiane ; - std() : écart-type ; - min() : minimum; - max() :
maximum - mad() : écart absolu à la moyenne ; - sum() : somme des valeurs ; -
prod() : produit de tous les éléments ; - count() : comptage du nombre
d’éléments. Une méthode très pratique est describe(), elle permet de retourner
des statistiques descriptives sur l’ensemble des colonnes numériques :
>>>print(df.describe())
- Tri : Il est aisé de trier un dataframe par ordre croissant ou décroissant d’une
ou plusieurs de ses colonnes. Pour ce faire, on utilise la méthode sort_values().
La syntaxe est la suivante : DataFrame.sort_values(by, axis=0,
ascending=True, inplace=False, kind="quicksort", na_position="last")
o by : nom ou liste de nom de la ou les colonnes utilisées pour effectuer le
tri ;
o axis : 0 pour l’index (par défaut), 1 pour les colonnes
o ascending : booléen ou liste de booléens, quand True le tri est fait par
valeurs croissantes (par défaut), quand False il est effectué par valeurs
décroissantes
o inplace : si True, le tri affecte le dataframe, sinon il retourne une vue ;
o kind : choix de l’algorithme de tri (quicksort (par défaut), mergesort,
heapsort) ;
o na_position : si first, les valeurs manquantes sont placées au début ; si
last (par défaut), à la fin.
- Concaténation : Il est fréquent d’avoir des données en provenance de plusieurs
sources lorsque l’on réalise une analyse. Il est alors nécessaire de pouvoir
combiner les différentes sources dans une seule. La syntaxe de concaténation
est la suivante : pd.concat([liste des dataframes séparés par « , »], axis = 0/1)
- Jointure : Il est plus fréquent d’avoir recours à des jointures un peu plus
élaborées pour rassembler les différentes sources de données en une seule.
pandas offre un moyen performant pour rassembler les données, la fonction
merge(). La fonction merge() de pandas nécessite de préciser la table de
gauche (que l’on appellera ici x) via le paramètre left sur qui viendra s’effectuer
la jointure de la table de droite (que l’on appellera ici y) via le paramètre right :
pd.merge(left = x, right = y). Par défaut, la fonction merge() réalise une
jointure de type inner, c’est-à-dire que toutes les toutes les lignes de x qui
trouvent une correspondance dans y, et toutes les colonnes de x et y seront
dans le résultat de la jointure. Si on désire changer le type de jointure, on peut
modifier la valeur du paramètre how de la fonction merge(), pour lui donner
une des valeurs suivantes :
o left : toutes les lignes de x, et toutes les colonnes de x et y. Les lignes
dans x pour lesquelles il n’y a pas de correspondance dans y auront des
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

valeurs NaN dans les colonnes. S’il y a plusieurs correspondances dans


les noms entre x et y, toutes les combinaisons sont retournées ;
o inner : toutes les lignes de x pour lesquelles il y a des valeurs
correspondantes dans y, et toutes les colonnes de x et y. S’il y a
plusieurs correspondances dans les noms entre x et y, toutes les
combinaisons possibles sont retournées ;
o right : toutes les lignes de y, et toutes les colonnes de y et x. Les lignes
dans y pour lesquelles il n’y a pas de correspondance dans x auront des
valeurs NaN dans les nouvelles colonnes. S’il y a plusieurs
correspondances dans les noms entre y et x, toutes les combinaisons
sont retournées ;
o outer : toutes les lignes de x et de y, et toutes les colonnes de x et y. Les
lignes de x pour lesquelles il n’y a pas de correspondance dabs y et celles
de y pour lesquelles il n’y a pas de correspondance dans x auront des
valeurs NaN.
- Agrégation : Pour effectuer le regroupement, en fonction de facteurs avant
d’effectuer les calculs d’agrégation, pandas propose la méthode groupby(). On
lui fournit en paramètre le ou les noms de colonnes servant à effectuer les
groupes.

XII. Importation des données


Pandas propose de nombreuses fonctions pour importer des données. Dans cette
version des notes de cours, nous allons en aborder 2 : read_csv(), pour lire des
fichiers CSV ; read_excel(), pour lire des fichiers Excel.
1. Fichier CSV
Pour importer des données depuis un fichier CSV, pandas propose la fonction
read_csv() : pandas.read_csv(chemin, paramètres) :
Parmi les paramètres que l’on utilise fréquemment :
- sep, delimiter : séparateur de champs ;
- decimal : séparateur de décimales ;
- header : numéro(s) de ligne(s) à utiliser comme en-tête des données ;
- skiprows : numéro(s) de ligne(s) à sauter au début ;
- skipfooter : numéro(s) de ligne(s) à sauter à la fin ;
- nrows : nombre de ligne à lire ;
- na_values : chaînes de caractères supplémentaires à considérer comme
valeurs manquantes (en plus de #N/A, #N/A N/A, #NA, -1.#IND, -
1.#QNAN, -NaN, -nan, 1.#IND, 1.#QNAN, N/A, NA, NULL, NaN, n/a,
nan, null) ;
- quotechar : caractère de quote ;
- encoding : encodage des caractères (défaut utf-8).
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

2. Fichier Excel
Pour importer des fichiers Excel, pandas propose la fonction read_excel() :
pandas.read_excel(chemin, paramètres).
Parmi les paramètres fréquemment utilisés :
- header : numéro de ligne à utiliser comme en-tête ;
- sheet_name: nom ou numéro de feuille ;
- skiprows : nombre de lignes à sauter au début ;
- thousands : séparateur de milliers.

XIII. Travaux pratiques


Exercice 1 : Génération des données aléatoires
1. Importer le module random puis générer un échantillon gaussien N(µ, σ2) de
taille n = 100 avec µ= 10 et σ= 2.

2. Ecrire une fonction moyenne(data), puis une fonction variance(data) et


ecartType(data) qui calcule la moyenne/variance/écart type d’un échantillon
data.

3. Vérifiez les résultats de l’application de vos fonctions avec celles du module


numpy

Exercice 2 : Manipulation de tableaux de données


1. À l’aide de la fonction read_excel() de la librairie pandas, importer le contenu
de la feuille intitulée notes_2012 du fichier Excel donné dans le dossier du TP
et le stocker dans une variable que l’on nommera notes_2012.
2. Afficher les 6 premières lignes du jeu de données, puis les dimensions du
tableau.
3. Conserver uniquement la colonne note_stat du tableau de données
notes_2012 dans un objet que l’on appellera tmp.
4. Conserver uniquement les colonnes num_etudiant, note_stat et note_macro
dans un objet nommé tmp.
5. Remplacer le contenu de tmp par les observations de notes_2012 pour
lesquelles l’individu a obtenu une note de stat supérieure (strictement) à 10.
6. Remplacer le contenu de tmp par les observations de notes_2012 pour
lesquelles l’individu a obtenu une note de stats comprise dans l’intervalle (10,
15).
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

7. Regarder s’il y a des doublons dans le tableau de données notees_2012 ; le cas


échéant, les retirer du tableau (utilisez la fonction drop_duplicates() sur le
dataframe).
8. Afficher le type des données de la colonne num_etudiant, puis afficher le type
de toutes les colonnes de notes_2012.
9. Ajouter au tableau notes_2012 les colonnes suivantes :
(a) note_stat_maj : la note de stat (note_stat) majorée d’un point,
(b) note_macro_maj : la note de macro (note_macro) majorée de trois points
(le faire en deux étapes : d’abord deux points en plus, puis un point).
10. Renommer la colonne year en annee, utilisez la méthode rename().
11. Depuis le fichier notes_etudiants.xlsx (c.f. question 1), importer le contenu des
feuilles notes_2013, notes_2014 et prenoms et le stocker dans les objets
notes_2013, notes_2014 et prenoms, respectivement.
12. Empiler le contenu des tableaux de données notes_2012, notes_2013 et
notes_2014 dans un objet que l’on nommera notes.
13. Fusionner les tableaux notes et prenoms à l’aide d’une jointure gauche, de
manière à rajouter les informations contenues dans le tableau prenoms aux
observations de notes. La jointure doit se faire par le numéro d’étudiant et
l’année, l’objet final viendra remplacer le contenu de notes.
14. Trier le tableau notes par années croissantes et notes de macro décroissantes.
15. Créer une colonne apres_2012 qui prend la valeur True si l’observation
concerne une note attribuée après 2012.
16. En effectuant des regroupements sur le dataframe notes, calculer :
(a) la moyenne et l’écart-type annuels des notes pour chacune des deux
matières,
(b) la moyenne et l’écart-type annuels et par sexe des notes pour chacune des
deux matières.

Exercice 3 : Visualisation des données


1. importez les bibliothèques NumPy et Pandas pour le traitement des données.
Importez le module pyplot pour le tracé des données et le module cm pour la
palette de couleurs du module Matplotlib.
2. Lisez à l’aide de la fonction read_csv() du module pandas les données du
fichier dataset_world.csv dans une variable nommé dataset et utilisez la
fonction head() pour vérifier les données
3. A l’aide de la fonction drop(), supprimez les colonnes du code du pays
(Country Code), de nom et code de l’indicateur (Indicator Name & Indicator
Code), les colonnes des années ayant des valeurs manquantes NaN et les
colonnes sans nom (Unamed).
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

4. Appliquez cette ligne de code afin de supprimer toutes les lignes où il peut y
avoir des valeurs vides ou nulles.
dataset.dropna(how = 'any', axis = 0, inplace = True)
Vérifiez qu’aucune colonne n’a de valeurs nulles en utilisant
dataset.isull().sum(), vous devriez avoir 0 valeur nulle pour toutes les lignes.
5. Nous commençons par analyser la densité de la population d’Aruba au cours
des années en utilisant un graphique linéaire. Nous prenons les années sur
l’axe des x et la densité de population sur l’axe des y.
Sélectionnez les valeurs x avec dataset.columns[1 :], ce qui sélectionne toutes
les colonnes sauf la première car nous n’avons besoin que des années et non
de la colonne Country Name.
Sélectionnez les valeurs y avec dataset.iloc[0][1 :], ce qui sélectionne la
première colonne, c’est-à-dire le pays Aruba et toutes les colonnes sauf la
première. Le nom du pays peut être obtenu à l’aide de dataset.iloc[0][0].
Pour tracer le graphique, il suffit d’utiliser la fonction plot et de définir les
paramètres comme x et y pour l’axe des x et l’axe des y respectivement.
6. Appliquez ces lignes de code:
plt.rcParams['figure.figsize'] = (30, 30)
plt.rcParams['font.size'] = '20'
plt.title('Densité de population ' + country + ' au cours des années')
plt.xlabel('Années')
plt.xticks(rotation = '90')
plt.ylabel('Densité de population (habitants par km2)')
plt.plot(x, y, linewidth = 4)
Que remarquez vous?
7. Reprenez l’affichage de la question précédente sur les 5 premiers pays.
Interprétez
8. Le diagramme en barres peut être facilement créé en utilisant la méthode
bar(),triez les densités de population de tous les pays pour l’année 2015 et
afficher le diagramme en bar des 10 premiers pays avec la densité maximale.
Interprétez.
9. Un diagramme de dispersion est un graphique qui affiche les données sous
forme de points dans l’espace libre. Nous analysons maintenant les pays où la
densité moyenne de population est inférieure à 10 personnes par kilomètre
carré (de surface terrestre) pour toutes les années.
total_columns = dataset.shape[1]
selected_data = dataset[dataset.sum(axis = 1).apply(lambda x:
x/total_columns) <= 10]
consolidated_data = selected_data.sum(axis = 1).apply(lambda x:
x/total_columns)
Université de Carthage Département Informatique Faculté des Sciences de Bizerte

Ces lignes de code permettent de faire la somme de toutes les données sur chaque
ligne en utilisant dataset.sum(axis = 1) et ensuite la méthode lambda est utilisée
pour dire que pour chaque valeur finale, il faut la diviser par le nombre de
colonnes pour obtenir la moyenne. Cette valeur est comparée par la suite à une
valeur inférieure ou égale à 10 et elle est utilisée comme indice pour l’ensemble
de données. Il en résulte l’ensemble des pays dont la densité moyenne de
population est inférieure ou égale à 10. Cette valeur est calculée à nouveau et elle
est stockée dans la variable consolidated_data.
Affichez à l’aide de la méthode scatter() le diagramme de dispersion
correspondant à ces données.

Vous aimerez peut-être aussi