Dans un précédent tutoriel, nous avons abordé les bases des boucles Python, en expliquant comment parcourir des listes et des listes de listes (ou listes imbriquées). Mais on peut faire bien plus avec des boucles for que parcourir des listes. Dans le monde réel, vous pouvez utiliser des boucles avec d’autres structures de données, par exemple des tableaux NumPy ou même des DataFrames pandas. Je vous présente dans cet article les boucles FOR Python techniques avancées.
Ce tutoriel commencera par traiter de l’utilisation des boucles for pour parcourir des structures de données Python communes autres que des listes (telles que des n-uplets et des dictionnaires). Nous allons ensuite explorer les boucles for directement avec les bibliothèques scientifiques Python courantes telles que NumPy, Pandas et Matplotlib. Nous allons également examiner de plus près la fonction range() et son utilité lors de l’écriture de boucles.
Structure générale : Boucles FOR Python Techniques avancées
Une boucle for est une instruction de programmation qui demande à Python de parcourir une collection d’objets en effectuant la même opération sur chaque objet en séquence. La syntaxe de base est la suivante :
for object in collection_of_objects: # code que vous souhaitez exécuter sur chaque objet
Chaque fois que Python parcourt la boucle, la variable object prend la valeur du prochain élément de notre séquence collection_of_objects et Python exécutera le code que nous avons écrit pour chaque élément de collection_of_objects.
Voyons maintenant comment utiliser les boucles for avec différentes sortes de structures de données. Nous allons sauter des listes puisque celles-ci ont été entièrement couvertes dans le précédent tutoriel.
Les structures de données
Tuples
Les tuples sont des séquences, tout comme des listes. La différence entre les tuples et les listes est que les tuples sont immuables; c’est-à-dire qu’ils ne peuvent pas être changés (en savoir plus sur les objets mutables et immuables en Python). Les tuples utilisent également des parenthèses au lieu des crochets.
Indépendamment de ces différences, les boucles sur les tuples ressemblent beaucoup aux listes.
x = (10,20,30,40,50) for var in x: print("index "+ str(x.index(var)) + ":",var)
index 0: 10 index 1: 20 index 2: 30 index 3: 40 index 4: 50
Si nous avons une liste de n-uplets, nous pouvons accéder aux éléments individuels de chaque tuple de notre liste en les incluant tous les deux en tant que variables dans la boucle for, comme suit:
x = [(1,2), (3,4), (5,6)] for a, b in x: print(a, "+", b, "=", a+b)
1 + 2 = 3 3 + 4 = 7 5 + 6 = 11
Dictionnaires
Outre les listes et les n-uplets, les dictionnaires sont un autre type de données Python courant que vous êtes susceptible de rencontrer lorsque vous travaillez avec des données. Les boucles for peuvent également effectuer une itération dans des dictionnaires.
Les dictionnaires Python sont composés de paires clé-valeur (key-value). Ainsi, dans chaque boucle, il faut accéder à deux éléments (la clé et la valeur). Au lieu d’utiliser enumerate() comme nous le ferions avec des listes, il est nécessaire d’appeler la méthode .items() pour parcourir les deux clés et les valeurs correspondantes de chaque paire clé-valeur.
Par exemple, imaginons que nous ayons un dictionnaire appelé stocks qui contient à la fois des actions boursières et les cours boursiers correspondants. Nous utiliserons la méthode .items() sur notre dictionnaire pour générer une clé et une valeur pour chaque itération :
stocks = { 'AAPL': 187.31, 'MSFT': 124.06, 'FB': 183.50 } for key, value in stocks.items() : print(key + " : " + str(value))
AAPL : 187.31 MSFT : 124.06 FB : 183.5
Notez que les noms key et value sont complètement arbitraires, nous pourrions aussi utiliser k et v ou encore x et y.
Strings
Comme indiqué dans le tutoriel d’introduction, les boucles for peuvent également parcourir chaque caractère d’une chaîne strings. En résumé, voici comment cela fonctionne :
print("data science") for c in "data science": print(c)
data science d a t a s c i e n c e
Tableaux NumPy
Voyons maintenant comment les boucles for peuvent être utilisées avec les bibliothèques Python courantes de Data Science et leurs types de données.
Nous allons commencer par regarder comment utiliser les boucles avec des tableaux numpy. Commençons par créer des tableaux de nombres aléatoires.
import numpy as np np.random.seed(0) # seed aléatoire pour reproduire le même résultat x = np.random.randint(10, size=6) y = np.random.randint(10, size=6)
Itérer sur un tableau numpy à une dimension est très similaire à itérer sur une liste:
for val in x: print(val)
5 0 3 3 7 9
Et maintenant, si nous voulons parcourir un tableau à deux dimensions?
Si nous utilisons la même syntaxe que précédemment pour itérer un tableau à deux dimensions, nous ne pouvons qu’itérer des tableaux entiers à chaque itération.
# création du tableau 2 dimensions z = np.array([x, y]) for val in z: print(val)
[5 0 3 3 7 9] [3 5 2 4 7 6]
Un tableau à deux dimensions est constitué d’une paire de tableaux à une dimension. Pour visiter chaque élément plutôt que chaque tableau, nous pouvons utiliser la fonction numpy nditer(), un objet itérateur multidimensionnel qui prend un tableau comme argument.
Dans le code ci-dessous, nous allons écrire une boucle for qui parcourt chaque élément en passant z (notre tableau à deux dimensions) en tant qu’argument pour nditer() :
for val in np.nditer(z): print(val)
5 0 3 3 7 9 3 5 2 4 7 6
Comme nous pouvons le voir, ceci énumère d’abord tous les éléments de x, puis tous les éléments de y.
Lors de la lecture par boucle for de ces différentes structures de données, les dictionnaires nécessitent une méthode alors que les tableaux numpy nécessitent une fonction.
DataFrames Pandas
Lorsque nous travaillons avec des données en Python, nous utilisons souvent des DataFrames Pandas. Et heureusement, nous pouvons utiliser les boucles for pour les parcourir également.
Faisons ce travail avec un petit fichier CSV (cliquez ici pour le télécharger) qui enregistre le PIB, la capitale et la population de six pays différents. Nous lirons ceci dans un DataFrame pandas ci-dessous.
Pandas fonctionne un peu différemment de numpy, nous ne pourrons donc pas simplement répéter le processus numpy que nous avons déjà appris. Si nous essayons de parcourir un DataFrame pandas comme nous le ferions avec un tableau numpy, ceci afficherait simplement les noms des colonnes:
import pandas as pd df = pd.read_csv('gdp.csv', index_col=0) for val in df: print(val)
Capital GDP ($US Trillion) Population
Au lieu de cela, nous devons mentionner explicitement que nous souhaitons effectuer une itération sur les lignes du DataFrame. Nous faisons cela en appelant la méthode iterrows() sur le DataFrame et en affichant les données souhaitées (étiquette + ligne) où une ligne correspond à la série entière pandas.
for label, row in df.iterrows(): print(label) print(row)
Ireland Capital Dublin GDP ($US Trillion) 0.3337 Population 4784000 Name: Ireland, dtype: object United Kingdom Capital London GDP ($US Trillion) 2.622 Population 66040000 Name: United Kingdom, dtype: object United States Capital Washington, D.C. GDP ($US Trillion) 19.39 Population 327200000 Name: United States, dtype: object China Capital Beijing GDP ($US Trillion) 12.24 Population 1386000000 Name: China, dtype: object India Capital New Delhi GDP ($US Trillion) 2.597 Population 1339000000 Name: India, dtype: object Germany Capital Berlin GDP ($US Trillion) 3.677 Population 82790000 Name: Germany, dtype: object
Nous pouvons également accéder à des valeurs spécifiques d’une série pandas. Supposons que nous voulions seulement afficher la capitale de chaque pays. Nous pouvons spécifier que nous voulons seulement sortir de la colonne “Capital” comme ceci :
for label, row in df.iterrows(): print(label + " : " + row["Capital"])
Ireland : Dublin United Kingdom : London United States : Washington, D.C. China : Beijing India : New Delhi Germany : Berlin
Pour aller plus loin que de simples affichages, ajoutons une colonne en utilisant une boucle for. Ajoutons une colonne de PIB par habitant. Rappelez-vous que la méthode .loc[] est basée sur un pays (label). Dans le code ci-dessous, nous allons ajouter la colonne de PIB par habitant et calculer sa valeur pour chaque pays en divisant le PIB total par la population et en multipliant le résultat par un billion (car les chiffres du PIB sont indiqués en billions).
for label, row in df.iterrows(): df.loc[label,'gdp_per_cap'] = row['GDP ($US Trillion)']/row['Population '] * 1000000000000 print(df)
Capital GDP ($US Trillion) Population Country Ireland Dublin 0.3337 4784000 United Kingdom London 2.6220 66040000 United States Washington, D.C. 19.3900 327200000 China Beijing 12.2400 1386000000 India New Delhi 2.5970 1339000000 Germany Berlin 3.6770 82790000 gdp_per_cap Country Ireland 69753.344482 United Kingdom 39703.210176 United States 59260.391198 China 8831.168831 India 1939.507095 Germany 44413.576519
Pour chaque ligne de notre DataFrame, nous créons une nouvelle étiquette et nous définissons des données de ligne égales au PIB total divisé par la population du pays, et en les multipliant par 1T$ pour des milliers de dollars.
La fonction range()
Nous avons vu comment nous pouvons utiliser les boucles for pour itérer sur toute séquence ou structure de données. Mais que se passe-t-il si nous souhaitons parcourir ces séquences dans un ordre spécifique ou pour un nombre de fois spécifique?
Cela peut être accompli avec la fonction range() (fonction built-in de Python). En fonction du nombre de paramètres utilisés pour la fonction, vous pouvez décider du début et de la fin de cette série de nombres ainsi que de de la différence entre un nombre et le suivant. Notez que, comme pour les listes, le décompte de la fonction range() commence à 0 et non à 1.
On peut appeler la fonction range() de trois manières:
- range(stop)
- range(start, stop)
- range(start, stop, step)
range(stop)
range(stop) prend un paramètre – utilisé lorsque nous voulons effectuer une itération sur une série de nombres commençant à 0 et incluant tous les nombres jusqu’au numéro que nous avons défini, mais sans l’inclure.
for i in range(3): print(i)
0 1 2
range(start, stop)
range(start, stop) prend deux paramètres – où nous pouvons non seulement définir la fin de la série mais aussi le début. Vous pouvez utiliser range() pour générer une série de nombres de A à B en utilisant range(A, B).
for i in range(1, 8): print(i)
1 2 3 4 5 6 7
range(start, stop, step)
range(start, stop, step) prend trois arguments. Outre les valeurs minimale et maximale, nous pouvons définir la différence entre un nombre dans la séquence et le suivant. La valeur par défaut de ‘step’ est 1 si aucune valeur n’est fournie.
for i in range(3, 16, 3): print(i)
3 6 9 12 15
Notez que cela fonctionne de la même manière pour les séquences non numériques.
Nous pouvons également utiliser l’index des éléments dans une séquence pour itérer. L’idée principale consiste à calculer d’abord la longueur de la liste, puis à effectuer une itération sur la séquence dans la plage de cette longueur.
Prenons un exemple :
languages = ['Espagnol', 'Anglais', 'Français', 'Allemand', 'Irlandais', 'Chinois'] for index in range(len(languages)): print('Langue:', languages[index])
Langue: Espagnol Langue: Anglais Langue: Français Langue: Allemand Langue: Irlandais Langue: Chinois
Dans notre boucle for ci-dessus, nous examinons l’index de la séquence de nombres crée par range(). Notez que nous utilisons également la fonction len() dans ce cas, car la liste n’est pas numérique.
Pour chaque itération, nous exécutons notre instruction print. Donc, pour chaque index de range(len(languages)), nous voulons afficher une langue. Comme la longueur de notre séquence de langues est 6 (c’est-à-dire la valeur évaluée par len(languages)), nous pouvons réécrire l’instruction comme suit:
for index in range(6): print('Langue:', languages[index])
Langue: Espagnol Langue: Anglais Langue: Français Langue: Allemand Langue: Irlandais Langue: Chinois
Tracer des graphiques avec des boucles For
Lorsque nous souhaitons parcourir une collection, nous utilisons chaque élément pour générer un sous-graphique ou même pour tracer un nouveau graphique. Par exemple, prenons le dataset très populaire iris.csv populaire et effectuons des tracés avec des boucles for.
Considérons le graphique ci-dessous :
import pandas as pd import numpy as np import matplotlib.pyplot as plt df = pd.read_csv('iris.csv') # créer une figure et un axe fig, ax = plt.subplots() # nuage de points des données sepal_length et des données sepal_width ax.scatter(df['sepal_length'], df['sepal_width']) # fixer un titre et des intitulés d'axe ax.set_title('Iris Dataset') ax.set_xlabel('sepal_length') ax.set_ylabel('sepal_width')
Ci-dessus, nous avons tracé la longueur de chaque sépale par rapport à sa largeur, mais nous pouvons donner plus de signification au graphique en colorant chaque point de données par la classe d’espèces de chaque fleur. Une façon de le faire est de disperser chaque point séparément à l’aide d’une boucle for et de passer dans la couleur correspondante.
# créer un dictionnaire de couleurs colors = {'setosa':'r', 'versicolor':'g', 'virginica':'b'} # créer une figure et un axe fig, ax = plt.subplots() # tracer chaque point for i in range(len(df['sepal_length'])): ax.scatter(df['sepal_length'][i], df['sepal_width'][i], color=colors[df['species'][i]]) # fixer un titre et des intitulés d'axe ax.set_title('Iris Dataset') ax.set_xlabel('sepal_length') ax.set_ylabel('sepal_width')
Et si nous voulions visualiser la distribution univariée de certaines caractéristiques de notre dataset iris? Nous pouvons faire cela avec plt.subplot() qui crée un sous-graphique unique dans une grille composée du nombre de colonnes et de lignes que nous pouvons définir.
Sans plonger trop profondément dans la syntaxe matplotlib pour le moment, voici une brève description de chaque composant principal de notre graphique:
- plt.subplot() – utilisé pour créer notre grille 2 x 2 et définir la taille globale.
- zip() – il s’agit d’une fonction built-in Python qui simplifie énormément la lecture simultanée de plusieurs itérables de même longueur.
- axes.flatten(), où flatten() est une méthode de tableau numpy – renvoie une version aplatie de nos tableaux (colonnes).
- ax.set() – nous permet de définir tous les attributs de notre objet axes avec une seule méthode.
Opérations additionnelles
Boucles imbriquées
Python nous permet d’utiliser une boucle dans une autre boucle. Cela implique une boucle externe qui a, à l’intérieur, une boucle interne.
Considérez la structure suivante:
for iterator_var in sequence: for iterator_var in sequence: # ...
Les boucles imbriquées peuvent être utiles pour parcourir des éléments dans des listes composées de listes. Dans une liste composée de listes, si nous employons une seule boucle for, le programme affichera chaque liste interne sous la forme d’un élément :
languages = [['Espagnol', 'Anglais', 'Français', 'Allemand'], ['Python', 'Java', 'Javascript', 'C++']] for lang in languages: print(lang)
['Espagnol', 'Anglais', 'Français', 'Allemand'] ['Python', 'Java', 'Javascript', 'C++']
Afin d’accéder individuellement à chaque élément des listes internes, nous définissons une boucle for imbriquée:
for x in languages: print("------") for lang in x: print(lang)
------ Espagnol Anglais Français Allemand ------ Python Java Javascript C++
Ci-dessus, la boucle for externe parcourt la liste de listes principale (qui contient deux listes dans cet exemple) et la boucle for interne parcourt les listes individuelles elles-mêmes. La boucle externe exécute 2 itérations (pour chaque sous-liste) et à chaque itération, nous exécutons notre boucle interne en affichant tous les éléments des sous-listes respectives.
Cela nous indique que le curseur se déplace depuis la boucle la plus externe, traverse la boucle interne puis revient à la boucle for externe, jusqu’à ce que le curseur couvre toute la plage, ce qui correspond à 2 fois dans ce cas.
Continue et break pour les boucles
Les instructions de contrôle de boucle modifient l’exécution d’une boucle for de sa séquence normale.
Et si nous voulons filtrer une langue spécifique dans notre boucle interne, nous pouvons utiliser l’instruction continue pour le faire, ce qui nous permet de sauter une partie spécifique de notre boucle lorsqu’une condition externe est déclenchée.
for x in languages: print("------") for lang in x: if lang == "Allemand": continue print(lang)
------ Espagnol Anglais Français ------ Python Java Javascript C++
Dans notre boucle ci-dessus, dans la boucle intérieure, si lang est égal à “Allemand” alors oublie cette itération uniquement et on continue avec le reste de la boucle. La boucle n’est pas terminée.
Regardons un exemple numérique maintenant :
from math import sqrt number = 0 for i in range(10): number = i ** 2 if i % 2 == 0: continue # continue ici print(str(round(sqrt(number))) + ' au carré est égal à ' + str(number))
1 au carré est égal à 1 3 au carré est égal à 9 5 au carré est égal à 25 7 au carré est égal à 49 9 au carré est égal à 81
Nous avons donc défini une boucle qui parcourt tous les chiffres de 0 à 9 et élève au carré chaque chiffre. Dans notre boucle, à chaque itération, nous vérifions si le nombre est divisible par 2 (nombre pair), si c’est le cas, on continue à exécuter tout en ignorant cette itération.
Et la commande break? Cela nous permet de sortir entièrement d’une boucle lorsqu’une condition externe est remplie. Regardons un exemple simple pour comprendre son fonctionnement en utilisant le même exemple que ci-dessus :
number = 0 for i in range(10): number = i ** 2 if i == 7: break print(str(round(sqrt(number))) + ' au carré est égal à ' + str(number))
0 au carré est égal à 0 1 au carré est égal à 1 2 au carré est égal à 4 3 au carré est égal à 9 4 au carré est égal à 16 5 au carré est égal à 25 6 au carré est égal à 36
Dans l’exemple ci-dessus, on teste la valeur de i, si celle-ci vaut 7, la commande break arrête la boucle. Notre boucle itère donc sur les entiers de 0 à 6 avant de sortir complètement de la boucle.
Conclusion
Dans cet article, nous avons découvert des applications plus avancées des boucles for, ainsi que leur utilisation dans les workflows de Data Science classique.
Nous avons appris comment parcourir différents types de structures de données et comment utiliser des boucles avec des DataFrames pandas et la bibliothèque matplotlib pour créer plusieurs graphiques.