Mineure « Data Science » Frédéric Pennerath
PYTHON
OU LE COUTEAU SUISSE DU DATA SCIENTIST
Chapitre 2
Plan de travail
• Introduction à Python (débutants)
• Exercice : prétraitement des données
– Installer vos machines.
• Voir le script d’installation pour Ubuntu sur la page du cours (www.metz.supelec.fr/metz/personnel/pennerath/Cours/DataScience)
– Créer un compte sur challengedata.ens.fr – Etudier les compétitions.
– Former des trinômes, choisir un challenge et s’y inscrire.
– Télécharger les données de la compétition
– Commencer à explorer / mettre en forme / visualiser avec Pandas
• A faire pour la prochaine fois :
– Regarder les tutoriels Numpy et Pandas référencés sur la page du cours:
Mineure « Data Science » Frédéric Pennerath
PROGRAMMATION
Le langage Python
Python 2 (2000) et Python 3 (2008)
– Dans la lignée de Perl :
• Langage « script » : interprété, compilé à la volée en bytecode (fichiers .ypc)
• Faiblement typé (typage à l’exécution)
• Ramasse miette
• Types de base, listes, dictionnaires
• Programmation fonctionnelle (faible)
• Programmation orientée objet (faiblement typée)
• Introspection
– Apports par rapport à Perl :
• Syntaxe plus propre et très intuitive
• Grande richesse des bibliothèques
– Forces et faiblesses :
• Les plus : flexibilité, simplicité et rapidité de développement
• Les moins : relativement lent et gourmand en mémoire, peu robuste (plantage
à l’exécution)
Mineure « Data Science » Frédéric Pennerath
Les interpréteurs Python
python : interpréteur de base Python (2.7 ou 3)
>> python3 interpréteur en ligne
>> python3 script.py exécution d’un script (compilation en ligne)
IPython : interpréteur amélioré (2.7, ou 3)
>> ipython3
>> ipython3 script.py
>> ipython3 --matplotlib pour des affichages de courbes Jupyter: feuilles de calcul intégrées dans une page html
>> jupyter notebook & (jadis ipython3 notebook)
Implémentation Python : objet, type et adresse
type(1) # builtins.int isinstance(1, int) # True
type(True) # builtins.bool type(1.) # builtins.float type(1+1j) # builtins.complex type("1") # builtins.str
type([ 1, 2]) # builtins.list type(( 1, 2)) # builtins.tuple type({ 1, 2}) # builtins.set type({"1" :
1, 2: "2" }) # builtins.dict Toute valeur est un objet ayant un type
Type de v : type(v)
Tout objet d’un type T est dit instance de T.
id(1) # 10105824 id(1) # 10105824
id(3.14) # 140004852491320 id(3.14) # 140004852491344 Tout objet occupe une zone mémoire définie
par sa taille et son adresse.
Adresse de v : id(v)
Les valeurs usuelles (0, …, 256, True, False) sont stockées au démarrage dans des objets
immuables.
Les autres valeurs sont stockées dans des objets
créés dynamiquement.
Mineure « Data Science » Frédéric Pennerath
Implémentation Python : variable et immuabilité
a = [] ; id(a) # 140004852430088 b = a ; id(b) # 140004852430088 b.append(1) ; a # [1]
id(b) # 140004852430088
Un objet dont le type est muable est modifiable.
Une modification sur une variable dont l’objet est muable ne change pas l’adresse contenue dans la
variable mais modifie le contenu de la mémoire représentant l’objet pointé.
Attention aux effets de bord ! Exemples : list, set, dict
Un objet dont le type est immuable n’est pas modifiable. Une modification appliquée à une variable dont l’objet est immuable modifie l’adresse contenue dans la variable, qui pointe maintenant sur
un nouvel objet égal à l’objet modifié.
Exemples :
int, bool, float, complex, str, tuplea = [] ; id(a) # 140004852430088 b = a ; id(b) # 140004852430088 Les variables Python stockent l’adresse de
l’objet, pas l’objet lui-même.
id(1) # 10105824 id(2) # 10105856 a =
1; b = a
id(a) # 10105824 id(b) # 10105824 a +=
1id(a) # 10105856
id(b) # 10105824
Implémentation Python : méthodes et attributs
complex.conjugate(1j) # -1j
1j.
conjugate() # -1j
a = []
list.append(a,1) # [1]
a.append(2) # [1,2]
Un objet a des méthodes et des attributs caractéristiques de son type.
Les méthodes et attributs sont les membres d’un objet.
1j.
imag # 1.0
Une méthode d’un objet o est une fonction T.f(...) rattachée à son type T qui
prend o comme premier argument.
Une méthode T.f(o,…) peut être appelée selon la syntaxe o.f(…)
Un attribut a d’un objet o est une variable rattachée à o selon la syntaxe o.a
Certaines méthodes définissent des opérateurs
L1 = [1]; L2 = [2]
L = L1 + L2
L = L1.__add__(L2)
L = list.__add__(L1,L2)
Mineure « Data Science » Frédéric Pennerath
Implémentation Python : classe d’objets
Une classe est un type muable défini par l’utilisateur avec ses méthodes et ses attributs.
class Complexe:
def
__init__(self,r, i = 0):
self.reel = r self.imag = i def
conjugue(self):self.imag = -self.imag def
__str__(self):return str(self.reel) + " + " + str(self.imag) + "i"
def
__eq__(self,c):
if(not isinstance(c, Complexe)):
return False
return (self.reel == c.reel)
and (self.imag == c.imag)
c = Complexe(1,2) # Appel du constructeur
print(c) # 1 + 2i
c.conjugue()
c == Complexe(1,-2) # True La méthode __init__ est le
constructeur appelé lors de la création d’un objet de
la classe. Il définit les attributs de l’objet
self désigne l’objet courant. self.reel et self.imag sont ses attributs.
La méthode __str__ est appelée pour convertir l’objet en une chaîne de
caractères.
La méthode __eq__ est appelée lorsque l’objet sert
d’opérande gauche à l’opérateur == de
comparaison.
Inspection et manipulation des valeurs
help(v) / help(t) : renvoie la liste des opérations du type de v ou du type t
>> help(1)
dir(v) / dir(t) : liste les attributs d’une valeur ou d’un type
>> dir(int)
sys.getsizeof(v) : renvoie le nombre d’octets mémoire occupés par la valeur v
>> sys.getsizeof(1) → 24 Complétion sous IPython
>> 10.(tab) →
10.bit_length 10.denominator 10.numerator 10.conjugate 10.imag 10.real
<nom T de type>(v) : convertit la valeur v en une valeur de type T (si cela a un sens)
>> float("-3.14"’) → -3.14
>> str(3.14) → ’-3.14’
print(v) : affiche la valeur v
Mineure « Data Science » Frédéric Pennerath
Opérations de base
Opérations numériques (int, long, float, complex) :
–Calcul de mod
24−12 , 3
: >> ((2 ** 4 – 1) / 2) % 3
→ 1–
Calcul de Im
1+𝑗1+𝑗
: >> ((1+1j) /(1+1j).conjugate()).imag
→ 1.0–
Module math : >> import math; dir(math)
Comparaisons (tout type) : ==, !=, <, >, <=, >=, cmp(x,y)
>> cmp("abc","baa")
→ -1Mise à jour de variables : =,+=, -=, *=, … Opérations et fonctions sur les chaînes :
>> infinitif = "programmer"; langage = "python".title()
>> forme = "je " + infinitif .strip("er" ) + "e en " + langage
>> mots = forme.split()
>> "-".join(mots)
>> len(forme); forme.index("en"); forme.replace("Python", "Perl")
Les structures de contrôle
Les blocs d’instruction sont définis par indentation.
Remarques:
• Un bloc indenté ne peut être introduit qu’à la suite de « : » (if, while, def, etc)
• Faites attention à indenter un bloc de façon homogène (même nbr. de tab/espace)
Tests :
if condition1 :…
elif condition2 :
… else:
…
Boucles :
for x in range(min,max+1, step) :
…
while condition :
…
break # Sort de la boucle
continue # Passe à l’itération suivante while not(fini()):
pass # Boucle vide
Exceptions :
try :
…
raise Exception("erreur !") exceptException as e :
print("Error: {}"..format(e))
raise # Si on veut relancer l’exception
Mineure « Data Science » Frédéric Pennerath
Exercices
Exercice 1 : tests et boucles
Afficher la liste des nombres premiers compris 1 et n en testant s’il existe pour chaque entier un diviseur.
Exercice 2 : listes
Même exercice avec le crible d’Eratosthène Exercice 3 : dictionnaires et fichiers
Lire un fichier texte en entrée et écrire dans un fichier en sortie :
• Soit la liste des mots associés à leur fréquence
• Soit la liste des numéros des lignes où apparaissent un mot donné
Les paramètres seront passés en arguments de la ligne de commande.
Les listes et les tuples
• Les listes (list) et tuples (tuple) sont des séquences non typées :
L = [1, "a"]; T = (True, L)
• Les listes sont en réalité des tableaux dynamiques (equiv. aux vecteurs de la STL)
• Les listes sont mutables, les tuples non.
• Les tuples servent souvent à renvoyer des résultats multiples depuis une fonction.
>> (a,b) = (1,2) → a = 1; b = 2
>> L = [1, 2, "a", [ 1.], False]
>> type(L) → list
>> L[0] → 1
>> L[-1] → False
>> L[2:4] → ['a', [1.0]]
>> L.pop() → False
>> L.pop(0) → 1
>> L.append(False) → [2, 'a', [ 1.], True]
>> sorted(L) → [True, 2, [1.0], 'a']
>> L = list(range(2,5)) → [2, 3, 4]
>> [x*2 for x in L] → [4, 6, 8]
>> [x*2 for x in L if x % 2 == 0] → [4, 8]
Mineure « Data Science » Frédéric Pennerath
Les dictionnaires
Les dictionnaires (
dict) sont des tableaux associatifs (tables de hachage) non typés:
>> D={"a":1, 3: True}
>> D → {3: True, 'a': 1}
>> D["a"] → 1
>> D["b"] = 2 → {3: True, 'a': 1, 'b': 2}
>> D.keys() → ['a', 3, 'b']
>> D.values() → [1, True, 2]
>> D.pop(3) → True
>> try:
entry = dictionary[word]
except KeyError:
raise Exception("Unknown word " + word)
Les ensembles (set) sont des dictionnaires sans valeurs :
>> S={"a", 3}
Les dictionnaires et listes peuvent s’imbriquer (création facilitée de graphes, etc) :
>> FdD = {"nom": "fouille de données", "vol" : 24}
>> SIR = {"nom": "SIR", "mineures" : [ FdD, …]}
>> FdD[’majeure’] = SIR
>> SIR['mineures'][0]['majeure'] == SIR → True
Les fonctions
Liste d’arguments variable : def test(*positionnels, **mots_cles):
print("positionnels = " + str(positionnels) print("mots clés = " + str(mots_cles)
>> test(1,True, "a", a = 1, b = "b") positionnels = (1, True, 'a')
mots clés = {'a': 1, 'b': 'b'}
Déclaration de fonction :
defphrase(mots, p = '.', s = ' '):
’’’Construit une phrase a partir de mots’’’
mots[0] = mots[0].title() res = s.join(mots)
res += p
returnres
Appel de fonction :
>> mots = ["ceci", "est", "un", "test"]
>> phrase(mots)
→‘Ceci est un test.'>> phrase(mots,’;’,’-’)
→ 'Ceci-est-un-test;‘>> phrase(mots, s=’-’) →
'Ceci-est-un-test.'Mineure « Data Science » Frédéric Pennerath
Les scripts
• Fichier texte avec extension
.py• Exécution en ligne de commande :
python script.py arg1 arg2 …import sys
def phrase(mots, p = '.', s = ' '):
"""Creer une phrase a partir de mots
"""
mots[0] = mots[0].title() res = s.join(mots)
res += p return res
# Ici commence le code du main :
args = sys.argv # Arguments passés en ligne de commande args.pop(0) # Elimine le nom du script
print(phrase(args))
Exercices
Exercice 1 : tests et boucles
Afficher la liste des nombres premiers compris 1 et n en testant s’il existe pour chaque entier un diviseur.
Exercice 2 : listes
Même exercice avec le crible d’Eratosthène Exercice 3 : dictionnaires et fichiers
Lire un fichier texte en entrée et écrire dans un fichier en sortie :
• Soit la liste des mots associés à leur fréquence
• Soit la liste des numéros des lignes où apparaissent un mot donné
Les paramètres seront passés en arguments de la ligne de commande.
Mineure « Data Science » Frédéric Pennerath
Programmation fonctionnelle et fonctions lambda
Le type fonction
Les fonctions sont des valeurs dont les noms sont des variables :
>> def carre(x): return x*x
>> f = carre; f(2) → 4
>> carre = 1; carre(2) → TypeError: 'int' object is not callable
>> def map2(f, L):
return [f(x) for x in L]
>> map2(carre, range(1,5)) → [1, 4, 9, 16]
Fonctions lambda et paramétrisation d’algorithmes :
>> map(lambda x : x*x, range(1,5)); filter(lambda x : x%2 == 0, range(1,5))
>> L=[{"n" : 1, "m" : 3}, {"n" : 3, "m" : 2}, {"n" : 2, "m" : 1}]
>> sorted(L, key = lambda x: x["m"], cmp = lambda x,y: cmp(y,x))
→ [{'m': 3, 'n': 1}, {'m': 2, 'n': 3}, {'m': 1, 'n': 2}]
Les itérables et les boucles
Itérable : object renvoyant un itérateur utilisé par les boucles
for>> for x in <iterable> : print(x)
Exemples d’énumérations:
D’une liste :
>> for x in [1,2,3]: ...D’un tuple :
>> for x in (1,2,3): ...D’une chaîne :
>> for x in "abcd":D’un ensemble :
>> for x in {1,2,3}:Des clés d’un dictionnaire :
>> for x in {"a" : 1, "b" : 2, "c" : 3}:Des valeurs d’un dictionnaire :
>> for x in {"a" : 1, "b" : 2, "c" : 3}.values():Des lignes d’un fichier texte
>> for x in open(file= "fichier", mode = "r")Listes par compréhension
>> [x ** 3 for x in range(1,10) ] // Equivalent à map
>> [x for x in range(1,10) if (x % 2 == 0) ] // Equivalent à filter
>> [x ** 3 for x in range(1,10) if (x % 2 == 0) ] // Map + Filter
>> [(i,j) for i in range(1,5) for j in range(1,i+1)] // double itération
>> [(i,j) for i in range(1,5) if(i % 2 == 0) for j in range(1,i+1)]
Mineure « Data Science » Frédéric Pennerath
Les fichiers
Accès en lecture:
>> f = open(file=fileName, mode="r", encoding="utf-8", errors='replace')
>> for line in f:
>> ...
>> f.close()
Accès en écriture :
>> f = open(file=fileName, mode="w", encoding="utf-8")
>> print("passage à la ligne suivante", file = f)
>> print("sans saut de ligne", file = f, end = '')
>> f.close()
Enumérer les fichiers d’un répertoire :
>> from os import listdir
>> for fileName in listdir("."): print(filename)
L’écriture formatée de fichiers et les chaînes de formatage
Simple substitution :
>> S = "{} : capitale = {2}, surface = {1} m2"
>> S.format(’France’,674843, ’Paris’)
→ ’France : capitale = Paris, surface = 674843 m2’
Justification au centre à gauche et à droite:
>> S = "{:^10} : capitale = {:.<10}, surface = {:>10} m2"
>> S.format(’France’, ’Paris’, 674843)
→ ' France : capitale = Paris..., surface = 674843 m2'
Formattage des nombres
>> "{:.2f}".format(3.1415) → '3.14'
>> "{:.2e}".format(3.1415) → '3.14e+00'
>> "{:.1%}".format(0.1531) → '15.3%'
Mineure « Data Science » Frédéric Pennerath
L’analyse de fichiers et les expressions régulières
Expression régulière :
Décrit un ensemble des chaînes de caractères reconnues par un automate Langage des expressions régulières :
langage de spécification d’un automate
Exemple : \d+ succession de chiffres de 0 à 9 Utile pour analyser le contenu de fichiers textes
Compilation génération de l’automate
>> import re
>> S = "T = -40, P = 100, V = 2.1"
>> expr = re.compile(’\d+’)
>> expr.findall(S)
→ ['40', '100', '2', '1']
>> expr = re.compile('-?\d+\.?\d+') ; expr.findall(S)
→ ['-40', '100', '2.1']
>> expr.split(S)
→ ['T = ', ', P = ', ', V = ', '']
>> expr = re.compile('(\w+)\s*=\s*(-?\d+\.?\d+)') ; expr.findall(S)
→ [('T', '-40'), ('P', '100'), ('V', '2.1')]
Les expressions régulières
Expression Correspondance
. Tout caractère
[x-y] Tout caractère entre x et y inclus
\w, \d, \s Tout caractère alphanumérique, tout chiffre, tout espace
\W, \D, \S Négations de \w, \d, \s
exp* Occurrences de exp de 0 ou plusieurs fois exp+ Occurrences de exp au moins une fois exp? Occurrences de exp au plus 1 fois exp{n,m} Occurrences de exp de n à m fois
(exp) Fait correspondre exp à une variable $n exp1|exp2 Alternative entre exp1 et exp2
^,$ Correspond au début et à la fin de la chaîne
\x Caractère x, si x est un caractère spécial (.,*,\,+,?,|,…)
Mineure « Data Science » Frédéric Pennerath
Exercices
Exercice 1 : tests et boucles
Afficher la liste des nombres premiers compris 1 et n en testant s’il existe pour chaque entier un diviseur.
Exercice 2 : listes
Même exercice avec le crible d’Eratosthène Exercice 3 : dictionnaires et fichiers
Lire un fichier texte en entrée et écrire dans un fichier en sortie :
• Soit la liste des mots associés à leur fréquence
• Soit la liste des numéros des lignes où apparaissent un mot donné
Les paramètres seront passés en argument de la ligne de commande.
La programmation objet
class Poly:
'un polynome a coefs reels'
# Constructeur
def __init__(self, C=[]):
self.coefs = C
# Conversion str(self) def __str__(self):
L = [ "{:2.2f} X^{}".format(self.coefs[i],i) for i in range(len(self.coefs)) ] L.reverse()
return "+".join(L)
# Opération self + P def __add__(self, P):
L = [ (x + y) for (x,y) in zip(self.coefs, P.coefs) ] L += self.coefs[len(P.coefs):]
L += P.coefs[len(self.coefs):]
return Poly(L)
# Attributs statiques
Poly.X = Poly([0, 1]) # Monôme X Poly.I = Poly([1]) # Constante 1
from Poly import Poly P = Poly([0, 1])
print(P + Poly.X)
Fichier « Poly.py »
Mineure « Data Science » Frédéric Pennerath
Les itérateurs
Itérateur : permet l’énumération d’éléments (pas forcément de structures de données sous-jacentes)
Exemple : range(min, max, step)
>> L = list(range(1,10000))
>> sys.getsizeof(L) → 80056
>> G = range(1,10000)
>> sys.getsizeof(G) → 32 !!!
Itérateurs paresseux versus liste par compréhension
>> L2 = [ 2*x for x in G ]
>> sys.getsizeof(L2) → 87624
>> G2 = ( 2*x for x in G )
>> sys.getsizeof(G2) → 72 !!!
Exemple d’application : transformation d’un fichier en Θ(1)
>> f = open(fileName, 'r')
>> g = ( l.upper() for l in f )
>> for l in g: print(l)
Itérateurs et itérables « faits maison »
class Poly:
...
# Itérable : retourne un itérateur
def __iter__(self): return Iter(self.coefs) class Iter:
# Constructeur de l'itérateur def __init__(self, coefs):
self.it = iter(coefs) # Itérateur de la liste de coefs.
self.degre = -1
# next renvoie le prochain élément ou exception StopIteration def __next__(self):
while(True):
coef = next(self.it) # Peut produite une StopIteration self.degre += 1
if(coef != 0.): return(coef, self.degre)
# Un itérateur est un itérable def __iter__(self): return self
Mineure « Data Science » Frédéric Pennerath
Les générateurs
class Poly:
...
# Renvoie un générateur def getCoefs(self):
degre = 0
for c in self.coefs:
if(c != 0.):
# yield renvoie une valeur yield (degre, c)
degre += 1
…
for c in P.getCoefs():
print(c)