|
|
On est toujours dans l'Atelier **B** : un graphique simple, avec un axe des x et un axe des y.
|
|
|
|
|
|
Notions principales : **lire un fichier**, avec open ; **parser un fichier** à l'ancienne, avec split ; méthodes de type **read_csv** pour les fichiers bien structurés
|
|
|
Notions annexes: **dictionnaires**, **module pandas"", **tkinter.filedialog**, **context manager**
|
|
|
Notions principales : **lire un fichier**, avec open ; **parser un fichier** à l'ancienne, avec split ; méthodes de type **read_csv** pour les fichiers bien structurés
|
|
|
|
|
|
Maintenant que l'on a quelques clés pour tracer un graphique, on va se placer dans un cas fréquent : on a un fichier et on souhaite visualiser les données.
|
|
|
De toutes façons, il faut savoir lire les données dans un fichier, donc c'est l'occasion de voir comment se débrouiller en Python.
|
|
|
Notions annexes: **dictionnaires**, \*\*module pandas"", **tkinter.filedialog**, **context manager**
|
|
|
|
|
|
### B2) lire un fichier texte et extraire l'information
|
|
|
Maintenant que l'on a quelques clés pour tracer un graphique, on va se placer dans un cas fréquent : on a un fichier et on souhaite visualiser les données. De toutes façons, il faut savoir lire les données dans un fichier, donc c'est l'occasion de voir comment se débrouiller en Python.
|
|
|
|
|
|
Vous trouverez du code déjà écrit dans le fichier Python visu_chronique.py, avec la fonction lecteur_qj0_to_ts écrite pour lire des fichiers de débit journalier dans un des formats de la base Hydro2.
|
|
|
Normalement, le code est commenté, et vous êtes invités à vous approprier ce code. N'hésitez pas à tester les instructions dans la console comme on a fait précédemment, et essayer de réécrire votre propre fonction.
|
|
|
Du code est également déjà écrit dans un [fichier sur un REPL en ligne](https://replit.com/@CPoulard/Plotting-long-time-series#main.py)
|
|
|
### B2) lire un fichier texte et extraire l'information
|
|
|
|
|
|
Vous trouverez du code déjà écrit dans le fichier Python visu_chronique.py, avec la fonction lecteur_qj0_to_ts écrite pour lire des fichiers de débit journalier dans un des formats de la base Hydro2. Normalement, le code est commenté, et vous êtes invités à vous approprier ce code. N'hésitez pas à tester les instructions dans la console comme on a fait précédemment, et essayer de réécrire votre propre fonction. Du code est également déjà écrit dans un [fichier sur un REPL en ligne](https://replit.com/@CPoulard/Plotting-long-time-series#main.py)
|
|
|
|
|
|
Il existe des méthodes performantes pour lire des fichiers structurés (colonnes nommées et lignes), notamment dans pandas et seaborn (read_csv). Ici, le fichier à un format qui se prête moyennement bien aux lectures en bloc, et on va donc travailler à l'ancienne.
|
|
|
Au passage, on va manipuler plusieurs notions utiles de Python. .
|
|
|
Il existe des méthodes performantes pour lire des fichiers structurés (colonnes nommées et lignes), notamment dans pandas et seaborn (read_csv). Ici, le fichier à un format qui se prête moyennement bien aux lectures en bloc, et on va donc travailler à l'ancienne. Au passage, on va manipuler plusieurs notions utiles de Python. .
|
|
|
|
|
|
#### a) Définir le chemin vers le fichier
|
|
|
|
|
|
La fonction **lecteur_qj0_to_ts** prend comme argument un chemin complet, répertoire+fichier.
|
|
|
|
|
|
Plusieurs solutions pour définir ce chemin :
|
|
|
**1) je tape le chemin en clair dans le code**, avec des slash / et pas de backslash, qui est un code d'échappement.
|
|
|
Plusieurs solutions pour définir ce chemin : **1) je tape le chemin en clair dans le code**, avec des slash / et pas de backslash, qui est un code d'échappement.
|
|
|
|
|
|
``` python
|
|
|
```python
|
|
|
# j'entre directement le chemin sous forme de chaîne de caractère comme argument
|
|
|
ts = lecteur_qj0_to_ts("C:/WorkSpace/2020-BaO_MultiDSpa/Migrateurs/Meuse/B2220010_qj_hydro2_2019.txt")
|
|
|
# deuxième solution, je passe par une variable
|
|
|
chemin_complet = "C:/WorkSpace/2020-BaO_MultiDSpa/Migrateurs/Meuse/B2220010_qj_hydro2_2019.txt"
|
|
|
ts = lecteur_qj0_to_ts(chemin_complet)
|
|
|
|
|
|
```
|
|
|
|
|
|
**2) je demande à l'utilisateur de saisir le nom au clavier**
|
|
|
La commande **input** permet de demander à l'utilisateur de saisir une réponse au clavier. Comme il est possible de se tromper, il vaut mieux vérifier que le fichier existe ; deux modules offrent les fonctions nécessaires : **os** et **pathlib.Path**. On va utiliser la seconde.
|
|
|
**2) je demande à l'utilisateur de saisir le nom au clavier** La commande **input** permet de demander à l'utilisateur de saisir une réponse au clavier. Comme il est possible de se tromper, il vaut mieux vérifier que le fichier existe ; deux modules offrent les fonctions nécessaires : **os** et **pathlib.Path**. On va utiliser la seconde.
|
|
|
|
|
|
``` python
|
|
|
```python
|
|
|
chemin_complet= input("Entrez le chemin complet vers le fichier de données :")
|
|
|
# je vérifie si le fichier existe
|
|
|
from pathlib import Path
|
... | ... | @@ -43,24 +37,20 @@ La commande **input** permet de demander à l'utilisateur de saisir une réponse |
|
|
ts = lecteur_qj0_to_ts(chemin_complet)
|
|
|
else:
|
|
|
print("chemin ", chemin_complet, " non valide")
|
|
|
```
|
|
|
```
|
|
|
|
|
|
On peut écrire une boucle **while** qui repose la question tant que le chemin n'est pas valide.
|
|
|
|
|
|
**3) j'utilise une fonction de Tkinter**
|
|
|
C'est cette option en mode "vite fait sur le gaz" qui est choisie dans le REPL en ligne ; on cite également une manière plus "propre" d'utiliser cette fonctionnalité.
|
|
|
**3) j'utilise une fonction de Tkinter** C'est cette option en mode "vite fait sur le gaz" qui est choisie dans le REPL en ligne ; on cite également une manière plus "propre" d'utiliser cette fonctionnalité.
|
|
|
|
|
|
a) mode "vite fait sur le gaz"
|
|
|
**askopenfilename** est une méthode très pratique du le module tkinter.filedialog, qui propose aussi **askdirectory** , **asksaveafile**... [voir la doc](https://docs.python.org/3/library/dialog.html)
|
|
|
Tkinter est un module pour réaliser des interface graphique, qui est présent dans le Python "de base". Ses méthodes sont donc prévues pour être appelées en présence d'une interface. En l'absence de cette interface, Tkinter va se débrouiller et ouvrir quand même une interface dans un coin, qu'il faudra refermer.
|
|
|
a) mode "vite fait sur le gaz" **askopenfilename** est une méthode très pratique du le module tkinter.filedialog, qui propose aussi **askdirectory** , **asksaveafile**... [voir la doc](https://docs.python.org/3/library/dialog.html) Tkinter est un module pour réaliser des interface graphique, qui est présent dans le Python "de base". Ses méthodes sont donc prévues pour être appelées en présence d'une interface. En l'absence de cette interface, Tkinter va se débrouiller et ouvrir quand même une interface dans un coin, qu'il faudra refermer.
|
|
|
|
|
|
``` python
|
|
|
```python
|
|
|
from tkinter.filedialog import askopenfilename
|
|
|
chemin_complet= askopenfilename() # ouverture d'une fenêtre explorateur
|
|
|
```
|
|
|
```
|
|
|
|
|
|
b) avec création d'une "application temporaire"
|
|
|
Cette solution fonctionne bien, mais c'est un peu pénible d'avoir une fenêtre "en plus" qu'il faut fermer à la main, au risque de voir ces fenêtres se multiplier si appelle plusieurs fois des méthodes de tkinter.
|
|
|
Il est donc préférable de créer une interface, pour la détruire juste après l'appel à la méthode de filedialog.
|
|
|
b) avec création d'une "application temporaire" Cette solution fonctionne bien, mais c'est un peu pénible d'avoir une fenêtre "en plus" qu'il faut fermer à la main, au risque de voir ces fenêtres se multiplier si appelle plusieurs fois des méthodes de tkinter. Il est donc préférable de créer une interface, pour la détruire juste après l'appel à la méthode de filedialog.
|
|
|
|
|
|
```python
|
|
|
import tkinter as Tk
|
... | ... | @@ -72,14 +62,11 @@ root.title("fenêtre temporaire") |
|
|
root.protocol('WM_DELETE_WINDOW', self.root.withdraw) # pour empêcher sa fermeture
|
|
|
chemin = tk_filedialog.askopenfilename()
|
|
|
root.destroy() # on détruit la fenêtre
|
|
|
|
|
|
```
|
|
|
|
|
|
Si on utilise plusieurs fois les méthodes de filedialog, on propose de créer un "context manager" pour insérer des actions avant et après le bloc de code. La notion de context manager sort du cadre de ce premier atelier, même si on l'utilise pour ouvrir un ficher avec **with open() as...**. Ce qui suit est donc facultatif, au pire retenez que ça existe et vous y reviendrez quand vous en aurez besoin
|
|
|
|
|
|
* * * début de l'aparté sur les context managers appliqués aux méthodes de filedialog * * *
|
|
|
L'idée est de définir dans une classe ad-hoc ce que l'on fait avant et après l'exécution du bloc de code, dans les méthodes __enter__ et __exit__.
|
|
|
Cette notion est également pratique dans une classe "normale" pour définir des actions à la création et à la destruction d'une instance, si on le fait au sein d'un bloc introduit par with.
|
|
|
* début de l'aparté sur les context managers appliqués aux méthodes de filedialog \* \* \* L'idée est de définir dans une classe ad-hoc ce que l'on fait avant et après l'exécution du bloc de code, dans les méthodes **enter** et **exit**. Cette notion est également pratique dans une classe "normale" pour définir des actions à la création et à la destruction d'une instance, si on le fait au sein d'un bloc introduit par with.
|
|
|
|
|
|
```python
|
|
|
# un exemple simple de context manager pour tester
|
... | ... | @@ -104,16 +91,12 @@ del(papier_gras) |
|
|
with UnObjetPourTester("bouteille d'eau", "verte") as bouteille_eau:
|
|
|
print("on jette l'objet ", bouteille_eau.nom)
|
|
|
```
|
|
|
|
|
|
L'exemple ci-dessus écrit dans la console:
|
|
|
> tests de la notion de context manager
|
|
|
> Création de bouteille d'eau.
|
|
|
> on jette l'objet bouteille d'eau
|
|
|
> Destruction de bouteille d'eau ; hop dans la poubelle verte.
|
|
|
|
|
|
Les actions définies par __enter__ et __exit__ ne sont exécutées que dans le second cas. On n'a pas besoin de préciser "del(bouteille_eau)", la destruction se fait automatiquement à la fin du bloc introduit par with.
|
|
|
En s'appuyant sur cette notion, on a proposé deux scripts pour gérer la création et la destruction de la fenêtre encadrant l'appel à une méthode de filedialog.
|
|
|
Le premier, présenté ici, fait appel à une classe "fantôme", qui ne fait pas grand chose ; le seul intérêt réside dans ses méthodes __enter__ et __exit__ qui vont respectivement créer et détruire une instance de tkinter.Tk. L'appel à tkinter.filedialog.askopenfilename ou à tout autre module de tkinter se fait dans le bloc du with.
|
|
|
Le second, plus complet, prend en argument la fonction de tkinter.filedialog et l'exécute dans sa méthode __enter__ . Les méthodes sont exécutées dans cet ordre : __init__, __enter__ puis __exit__ ; pour vous en convaincre il suffit d'ajouter des **print**.
|
|
|
> tests de la notion de context manager Création de bouteille d'eau. on jette l'objet bouteille d'eau Destruction de bouteille d'eau ; hop dans la poubelle verte.
|
|
|
|
|
|
Les actions définies par **enter** et **exit** ne sont exécutées que dans le second cas. On n'a pas besoin de préciser "del(bouteille_eau)", la destruction se fait automatiquement à la fin du bloc introduit par with. En s'appuyant sur cette notion, on a proposé deux scripts pour gérer la création et la destruction de la fenêtre encadrant l'appel à une méthode de filedialog. Le premier, présenté ici, fait appel à une classe "fantôme", qui ne fait pas grand chose ; le seul intérêt réside dans ses méthodes **enter** et **exit** qui vont respectivement créer et détruire une instance de tkinter.Tk. L'appel à tkinter.filedialog.askopenfilename ou à tout autre module de tkinter se fait dans le bloc du with. Le second, plus complet, prend en argument la fonction de tkinter.filedialog et l'exécute dans sa méthode **enter** . Les méthodes sont exécutées dans cet ordre : **init**, **enter** puis **exit** ; pour vous en convaincre il suffit d'ajouter des **print**.
|
|
|
|
|
|
```python
|
|
|
# application de la notion de context manager pour utiliser filedialog; version simple
|
... | ... | @@ -139,63 +122,50 @@ with FenetrePourDialogue() as fenetre: |
|
|
print(chemin)
|
|
|
```
|
|
|
|
|
|
* * * fin de l'aparté sur les context managers appliqués aux méthodes de filedialog * * *
|
|
|
|
|
|
Dans tous les cas, il est utile de vérifier si le fichier existe.
|
|
|
Il n'est pas rare d'avoir des problèmes de format ; sur le REPL.IT vous trouverez deux fichiers dont le nom commence par "B2220010" ; un seul permet de faire tourner le code correctement. Si vous les ouvrez, vous ne verrez pas de différence au premier abord. Celui qui est déposé sur le gitlab a été d'abord copié sur le site REPL, mais le code ne pouvait pas l'ouvrir... On a "truandé" en ouvrant un fichier sur le REPL puis en copiant-collant les données dedans...
|
|
|
Si vous avez un Mac vous pourriez être amené à pratiquer le même genre de bidouille ou bien à rechercher le format du fichier d'entrée.
|
|
|
* fin de l'aparté sur les context managers appliqués aux méthodes de filedialog \* \* \*
|
|
|
|
|
|
Dans tous les cas, il est utile de vérifier si le fichier existe. Il n'est pas rare d'avoir des problèmes de format ; sur le REPL.IT vous trouverez deux fichiers dont le nom commence par "B2220010" ; un seul permet de faire tourner le code correctement. Si vous les ouvrez, vous ne verrez pas de différence au premier abord. Celui qui est déposé sur le gitlab a été d'abord copié sur le site REPL, mais le code ne pouvait pas l'ouvrir... On a "truandé" en ouvrant un fichier sur le REPL puis en copiant-collant les données dedans... Si vous avez un Mac vous pourriez être amené à pratiquer le même genre de bidouille ou bien à rechercher le format du fichier d'entrée.
|
|
|
|
|
|
#### b) Ouvrir le fichier et le lire ligne par ligne
|
|
|
|
|
|
Sur les deux supports, un code vous est déjà proposé.
|
|
|
Pratique recommandée pour ouvrir un fichier : "**with** open(nom_fichier, 'r') as alias_du_fichier".
|
|
|
Sur les deux supports, un code vous est déjà proposé. Pratique recommandée pour ouvrir un fichier : "**with** open(nom_fichier, 'r') as alias_du_fichier".
|
|
|
|
|
|
:baby: Si vous débutez : retenez que cette syntaxe est fortement recommandées ; si vous utilisez une autre façon de faire vous devrez bien penser à fermer le fichier à la fin.
|
|
|
:older_man: On a mentionné plus haut la notion de **context manager**.
|
|
|
:baby: Si vous débutez : retenez que cette syntaxe est fortement recommandées ; si vous utilisez une autre façon de faire vous devrez bien penser à fermer le fichier à la fin. :older_man: On a mentionné plus haut la notion de **context manager**.
|
|
|
|
|
|
<details><summary>un autre petit mot facultatif sur les context managers et les décorateurs </summary>
|
|
|
=> **with** introduit un **"context manager"** qui déclenche une action définie par la méthode dunder __start__ de la classe avant la première instruction, et une dernière action définie par la dunder __end__ à la fin. Ici, l'action finale est la fermeture du fichier, ce qui garantit que le fichier se fermera à la fin du bloc d'instructions, quoi qu'il arrive. Cela rappelle les décorateurs, sauf qu'ici on peut choisir d'appeler au cas par cas la classe avec un context manager ou pas, alors que les décorateurs modifient définitivement la fonction (surcharge).
|
|
|
On peut par exemple définir un context manager pour mesurer le temps d'exécution d'une fonction (au début : on note l'heure ; à la fin : on note l'heure et on calcule le délai).
|
|
|
</details>
|
|
|
|
|
|
|
|
|
Une fois le fichier ouvert, on va lire les lignes avec alias_du_fichier.readline().
|
|
|
Dans le code proposé, on va d'abord lire les lignes une à une jusqu'à en trouver une qui contienne un mot-clé.
|
|
|
Ensuite, on lit toutes les autres grâce à une simple boucle **for ligne_lue in alias_du_fichier**, qui lira les lignes une par une jusqu'à la fin. Grâce au context manager, le fichier sera fermé proprement à la fin du bloc de code.
|
|
|
<details>
|
|
|
<summary>un autre petit mot facultatif sur les context managers et les décorateurs</summary>
|
|
|
=> \*\*with\*\* introduit un \*\*"context manager"\*\* qui déclenche une action définie par la méthode dunder __start__ de la classe avant la première instruction, et une dernière action définie par la dunder __end__ à la fin. Ici, l'action finale est la fermeture du fichier, ce qui garantit que le fichier se fermera à la fin du bloc d'instructions, quoi qu'il arrive. Cela rappelle les décorateurs, sauf qu'ici on peut choisir d'appeler au cas par cas la classe avec un context manager ou pas, alors que les décorateurs modifient définitivement la fonction (surcharge). On peut par exemple définir un context manager pour mesurer le temps d'exécution d'une fonction (au début : on note l'heure ; à la fin : on note l'heure et on calcule le délai).
|
|
|
</details>Une fois le fichier ouvert, on va lire les lignes avec alias_du_fichier.readline(). Dans le code proposé, on va d'abord lire les lignes une à une jusqu'à en trouver une qui contienne un mot-clé. Ensuite, on lit toutes les autres grâce à une simple boucle **for ligne_lue in alias_du_fichier**, qui lira les lignes une par une jusqu'à la fin. Grâce au context manager, le fichier sera fermé proprement à la fin du bloc de code.
|
|
|
|
|
|
Chaque ligne récupérée sous forme de chaîne de caractères, **string**, et stockée dans une variable que nous avons appelée **ligne_lue**.
|
|
|
|
|
|
#### c) Extraire l'information utile : "parser" les lignes
|
|
|
Il nous faut maintenant extraire l'information des lignes lues.
|
|
|
On a supposé que nos données ne sont pas assez bien bien structurées pour utiliser les instructions modernes de type "read_csv" (du module pandas ou seaborn par exempe).
|
|
|
|
|
|
Il nous faut maintenant extraire l'information des lignes lues. On a supposé que nos données ne sont pas assez bien bien structurées pour utiliser les instructions modernes de type "read_csv" (du module pandas ou seaborn par exempe).
|
|
|
|
|
|
On réalise ici un parsing "à l'ancienne", ligne par ligne. Un peu pénible, certes, mais cette étape permet de réaliser des vérifications et de décomposer des éléments, ainsi que de manipuler des notions de liste et string.
|
|
|
|
|
|
Les commentaires du code + la diapo doivent vous guider.
|
|
|
Pour mieux comprendre les instructions de "découpage" des lignes (split) et leur transcription en dates et valeurs, manipulez dans la console la chaîne " QJO;B2220010;19680627;7330.000;C;9;"
|
|
|
Les commentaires du code + la diapo doivent vous guider. Pour mieux comprendre les instructions de "découpage" des lignes (split) et leur transcription en dates et valeurs, manipulez dans la console la chaîne " QJO;B2220010;19680627;7330.000;C;9;"
|
|
|
|
|
|
``` python
|
|
|
```python
|
|
|
ligne_lue_dans_le_fichier = "QJO;B2220010;19680627;7330.000;C;9;"
|
|
|
```
|
|
|
Effectuez ensuite des tests, par exemple
|
|
|
``` python
|
|
|
|
|
|
Effectuez ensuite des tests, par exemple
|
|
|
|
|
|
```python
|
|
|
"QJO" in ligne_lue_dans_le_fichier # retourne un booléen, vrai/faux (en Python, True ou False, avec une majuscule)
|
|
|
ligne_splitee = ligne_lue_dans_le_fichier.split(";") # ligne_splitee est une LISTE de STRINGS
|
|
|
ligne_splitee[1] # élément d'indice 1, est-ce le premier ???
|
|
|
ligne_splitee[2][0:4] # string composé des caractères d'indices 0 à 4 EXCLU de l'élément d'indice 2
|
|
|
valeur_numerique = float(ligne_splitee[3] )
|
|
|
```
|
|
|
```
|
|
|
|
|
|
#### d) stockage de l'information dans un dictionnaire
|
|
|
|
|
|
Si besoin, on fera un topo sur les dictionnaires, un type de conteneur central en python.
|
|
|
Le dictionnaire associe des clés à des valeurs.
|
|
|
On utilisera plusieurs fois des dictionnaires, on va donc découvrir ici une manière de créer un dictionnaire, et les principales instructions utiles.
|
|
|
La **clé** doit être d'un type NON-MUTABLE* (voir notes) ; évidemment, si la clé changeait on perdrait la relation clé-valeur. Les types string, datetime, chiffre... conviennent. Une liste ne convient pas.
|
|
|
La **valeur associée** peut être de n'importe quel type, y compris des conteneurs, et peut en théorie varier d'une clé à l'autre (mais en pratique il vaut mieux se tenir à un même type, ou au minimum à des types qui partagent les méthodes que l'on va devoir leur appliquer dans la suite...
|
|
|
Si besoin, on fera un topo sur les dictionnaires, un type de conteneur central en python. Le dictionnaire associe des clés à des valeurs. On utilisera plusieurs fois des dictionnaires, on va donc découvrir ici une manière de créer un dictionnaire, et les principales instructions utiles. La **clé** doit être d'un type NON-MUTABLE\* (voir notes) ; évidemment, si la clé changeait on perdrait la relation clé-valeur. Les types string, datetime, chiffre... conviennent. Une liste ne convient pas. La **valeur associée** peut être de n'importe quel type, y compris des conteneurs, et peut en théorie varier d'une clé à l'autre (mais en pratique il vaut mieux se tenir à un même type, ou au minimum à des types qui partagent les méthodes que l'on va devoir leur appliquer dans la suite...
|
|
|
|
|
|
``` python
|
|
|
```python
|
|
|
# définition d'un dictionnaire ; entre accolades
|
|
|
dictionnaire_main = {1:"un", 2:"deux", 3: "trois", 4:"quatre", 5: "cinq"} # dictionnaire avec couples clé: valeur
|
|
|
mon_dictionnaire_vide = dict() # dictionnaire vide
|
... | ... | @@ -213,35 +183,34 @@ mon_dictionnaire.values() # vue des valeurs ; ce n'est pas une liste mais c'es |
|
|
mon_dictionnaire.items() # vue des couples (clé, valeur) ; c'est un itérable* dont les éléments sont des tuples
|
|
|
for clef, valeur in mon_dictionnaire.items() :
|
|
|
print("clé = ", clef, " et valeur = ", valeur)
|
|
|
```
|
|
|
```
|
|
|
|
|
|
#### e) tracé à partir du dictionnaire, puis à partir d'une structure pandas Series
|
|
|
|
|
|
Ensuite, on compare 2 manière de tracer le graphique q(t) : d'abord à partir du dictionnaire ; pour cela il faut extraire du dictionnaire la liste_des_dates et la liste_des_q.
|
|
|
La doc indique que les dictionnaires n'existaient pas quand matplotlib a été développé, et il n'a pas été conçu au départ pour accepter directement un dictionnaire comme argument, ni même les vues keys et values d'un dictionnaire : il faut les convertir en **liste** d'abord pour les utiliser comme arguments.
|
|
|
Ensuite, on compare 2 manière de tracer le graphique q(t) : d'abord à partir du dictionnaire ; pour cela il faut extraire du dictionnaire la liste_des_dates et la liste_des_q. La doc indique que les dictionnaires n'existaient pas quand matplotlib a été développé, et il n'a pas été conçu au départ pour accepter directement un dictionnaire comme argument, ni même les vues keys et values d'un dictionnaire : il faut les convertir en **liste** d'abord pour les utiliser comme arguments.
|
|
|
|
|
|
``` python
|
|
|
```python
|
|
|
liste_des_dates= list(mon_dictionnaire.keys() ) # on convertit la vue en liste
|
|
|
liste_des_q = list(mon_dictionnaire.values() )
|
|
|
plt.plot(liste_des_dates, liste_des_q)
|
|
|
|
|
|
# ou directement
|
|
|
plt.plot(list(mon_dictionnaire.keys()),list(mon_dictionnaire.values())
|
|
|
```
|
|
|
On va tester le wrapper de pandas (méthode **mon_objet_pandas.plot()**)
|
|
|
Pour cela, on doit d'abord créer un objet de type pandas Series avec les données, sur lequel on appliquera la méthode plot : ma_series.plot().
|
|
|
```
|
|
|
|
|
|
On va tester le wrapper de pandas (méthode **mon_objet_pandas.plot()**) Pour cela, on doit d'abord créer un objet de type pandas Series avec les données, sur lequel on appliquera la méthode plot : ma_series.plot().
|
|
|
|
|
|
La conversion est facile, puisque le module pandas, lui, accepte un dictionnaire comme argument.
|
|
|
|
|
|
On introduit dans ce 2e cas un type de courbe "en créneaux" qui convient mieux à des valeurs moyennes journalières.
|
|
|
|
|
|
Remarque : comment exécuter une fonction à la fois pour suivre le déroulement de l'atelier ?
|
|
|
C'est vrai qu'un notebook est bien pratique pour avancer étape par étape.
|
|
|
Ici, on va mettre en oeuvre l'une ou l'autre de ces deux techniques :
|
|
|
Remarque : comment exécuter une fonction à la fois pour suivre le déroulement de l'atelier ? C'est vrai qu'un notebook est bien pratique pour avancer étape par étape. Ici, on va mettre en oeuvre l'une ou l'autre de ces deux techniques :
|
|
|
|
|
|
1) écrire les instructions dans le "corps du programme", précédé ici d'un test pour activer certaines sous-parties au fur et à mesure du déroulé
|
|
|
```plaintext
|
|
|
1) écrire les instructions dans le "corps du programme", précédé ici d'un test pour activer certaines sous-parties au fur et à mesure du déroulé
|
|
|
```
|
|
|
|
|
|
``` python
|
|
|
```python
|
|
|
if __name__ == '__main__':
|
|
|
# bloc d'instructions qui ne s'exécute que si le fichier est exécuté en temps que programme principal
|
|
|
#donc qui ne s'exécutera pas si le fichier est importé comme module d'un autre programme
|
... | ... | @@ -249,13 +218,17 @@ if __name__ == '__main__': |
|
|
if premier_atelier:
|
|
|
# instructions pour le premier atelier
|
|
|
#
|
|
|
```
|
|
|
2) travailler dans la console et utiliser le fichier comme un module. La ligne en début de corps de programme qui vous intrigue peut-être est justement là pour permettre d'utiliser le fichier comme module sans déclencher l'exécution des instructions.
|
|
|
```
|
|
|
|
|
|
```plaintext
|
|
|
2) travailler dans la console et utiliser le fichier comme un module. La ligne en début de corps de programme qui vous intrigue peut-être est justement là pour permettre d'utiliser le fichier comme module sans déclencher l'exécution des instructions.
|
|
|
```
|
|
|
|
|
|
Voilà ce qui doit se passer dans la console :
|
|
|
``` python
|
|
|
|
|
|
```python
|
|
|
from Atelier_MatPlotLib_2021_part1 import lecteur_qj0_to_ts
|
|
|
from tkinter.filedialog import askopenfilename # parce qu'on en a besoin dans la console
|
|
|
chemin_complet = askopenfilename()
|
|
|
ts = lecteur_qj0_to_ts(chemin_complet)
|
|
|
```
|
|
|
|
|
|
``` |
|
|
\ No newline at end of file |