Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Cette section vise à vous donner de nouvelles compétences en Python pour manipuler des données structurées et tabulaires.

Objectifs d’apprentissage :

  • Manipuler des tables de données (data frames) : les décrire, les filtrer…
  • Découvrir les fonctions lambda
  • Introduction aux objets datetime
  • Tracer des données issues de tables de données (histogrammes et cartes)
  • Introduction à Plotly
  • Introduction à CSV & Parquet

Ce tutoriel peut être donné en un cours de 2 heures. Les sections sont étiquetées Niveau 1, 2, 3 dans les sections 1, 2, 3, et les enseignants peuvent réserver les niveaux supérieurs à un apprentissage asynchrone, en autonomie.

Nous travaillerons sur plusieurs jeux de données structurés : métadonnées de capteurs, produit de données sismologiques (catalogue de séismes).

Importons d’abord tous les modules nécessaires :

🖥️ Diapositives du cours — Séance 05 (ven. 9 oct.)

Ce carnet (notebook) utilise plotly pour produire des tracés interactifs

1 Fondamentaux de Pandas

1.1 Bases

Les objets centraux de Pandas sont Series et DataFrame. Une Series est un tableau étiqueté unidimensionnel. Le DataFrame est une table bidimensionnelle dont les colonnes sont des Series.

Nous pouvons créer de toutes pièces un DataFrame composé de séries à partir d’un dictionnaire Python :

   temperature  precipitation
0           36              3
1           37              1
2           30              0
3           50              0

Chaque élément (clé, valeur) du DataFrame correspond à une valeur de data. Pour obtenir les clés du DataFrame, tapez :

Index(['temperature', 'precipitation'], dtype='str')

obtenir une Series donnée (différente du tableau)

0    36
1    37
2    30
3    50
Name: temperature, dtype: int64
<class 'pandas.Series'>

pour obtenir la valeur d’une clé donnée (la température, par exemple), à un indice donné (2, par exemple), tapez :

30
<class 'numpy.int64'>

1.2 Lire un DataFrame depuis un fichier CSV

Nous pouvons lire un DataFrame pandas directement depuis un fichier standard. Nous téléchargerons un catalogue de séismes avec pooch, qui met le fichier en cache dans le dossier local data/.

Utilisez maintenant la fonction head pour afficher le contenu du fichier

Loading...

Affichez la profondeur en utilisant l’objet pandas de deux manières

0        34400.0
1        30100.0
2        16900.0
3       109400.0
4        25700.0
          ...   
1780     10000.0
1781    105000.0
1782    608510.0
1783     10000.0
1784     35440.0
Name: depth, Length: 1785, dtype: float64
0        34400.0
1        30100.0
2        16900.0
3       109400.0
4        25700.0
          ...   
1780     10000.0
1781    105000.0
1782    608510.0
1783     10000.0
1784     35440.0
Name: depth, Length: 1785, dtype: float64

Calculez des statistiques de base des données avec la fonction describe.

Loading...

Calculez la moyenne et la médiane d’une Series donnée, par exemple la profondeur.

82773.18767507003
24400.0

1.3 Manipuler Pandas avec Python

Fonctions classiques

Nous allons maintenant nous exercer à modifier le contenu du DataFrame à l’aide de fonctions. Prenons l’exemple où nous voulons convertir les valeurs de profondeur de mètres en kilomètres. Nous pouvons d’abord définir cette opération comme une fonction

np.float64(34.4)

Définissons une autre fonction qui utilise une variable locale plutôt que globale

Loading...

Fonctions lambda

Nous abordons maintenant les fonctions lambda.

  • Les fonctions lambda sont de petites fonctions anonymes en Python.
  • Elles servent à des opérations rapides et simples, sans qu’il faille définir une fonction complète avec def.
  • En géosciences, où l’on traite de grands jeux de données (données climatiques, mesures sismiques…), les fonctions lambda permettent de traiter les données efficacement.
  • Dans Pandas, les fonctions lambda permettent de transformer, filtrer ou traiter rapidement ces données avec un minimum de code.
  • Lisez aussi les tutoriels de RealPython (en anglais).
<function __main__.<lambda>(x)>

Cette fonction lambda multiplie toute entrée x par 1,2, ce qui peut servir à des tâches comme des conversions d’unités (de km en m, par exemple).

Voici un exemple d’utilisation de lambda dans un DataFrame pandas. Exemple 1 : La fonction lambda x: (x - 32) * 5 / 9 convertit des degrés Fahrenheit en degrés Celsius pour chaque valeur de la colonne Temperature_F.

   Temperature_F  Temperature_C
0             32       0.000000
1             50      10.000000
2             77      25.000000
3            100      37.777778

Appliquez maintenant la fonction à la série entière

0 34.40 1 30.10 2 16.90 3 109.40 4 25.70 ... 1780 10.00 1781 105.00 1782 608.51 1783 10.00 1784 35.44 Name: depth, Length: 1785, dtype: float64

Les fonctions lambda peuvent prendre plusieurs entrées

1

Cela n’a pas modifié les valeurs du DataFrame, vérifiez-le :

0 34400.0 1 30100.0 2 16900.0 3 109400.0 4 25700.0 ... 1780 10000.0 1781 105000.0 1782 608510.0 1783 10000.0 1784 35440.0 Name: depth, Length: 1785, dtype: float64

Vous pourriez à la place écraser quake.depth=X. Essayez les deux approches, mais ne le faites qu’une seule fois ! Vous pouvez utiliser les fonctions Python map (une fonction pour appliquer des fonctions, générique en Python) et apply (une fonction pour appliquer des fonctions, propre à Pandas).

Essayez map pour appliquer une fonction lambda qui convertit la profondeur de mètres en kilomètres.

À discuter en classe : qu’est-il arrivé au champ de profondeur ?

Qu’est-il arrivé au DataFrame d’origine ?

Essayez apply pour appliquer une fonction lambda qui convertit la profondeur de mètres en kilomètres. Ici, nous affichons seulement le résultat sans l’assigner, car la cellule précédente a déjà converti la colonne en kilomètres.

0 0.03440 1 0.03010 2 0.01690 3 0.10940 4 0.02570 ... 1780 0.01000 1781 0.10500 1782 0.60851 1783 0.01000 1784 0.03544 Name: depth, Length: 1785, dtype: float64

Tracez un histogramme des distributions de profondeur avec la fonction matplotlib hist.

<Figure size 640x480 with 1 Axes>

Vous pouvez utiliser le paquet de visualisation interactive Plotly. Nous montrerons d’abord un histogramme de la profondeur des événements avec la fonction histogram.

Loading...

Exemple 2 : logique conditionnelle sur la magnitude des séismes

Vous pouvez utiliser des fonctions lambda pour ajouter de la logique conditionnelle, par exemple pour classer les magnitudes de séismes en catégories.

Scénario : vous avez une colonne Magnitude contenant des magnitudes d’événements sismiques, et vous voulez classer les événements en « Minor » (mineur), « Moderate » (modéré) ou « Severe » (sévère).

Loading...

Nous allons maintenant faire un nouveau tracé de la position des séismes, avec l’outil Plotly.

La taille des marqueurs sera proportionnée à la magnitude du séisme. Pour cela, nous ajoutons une série marker_size au DataFrame

1.4 Manipulation intermédiaire avec Pandas

Vous pouvez aussi appliquer des fonctions lambda sur plusieurs colonnes, ce qui est courant dans les jeux de données géoscientifiques, où l’on manipule souvent des données spatiales ou temporelles.

Exemple 3 : calculer un indice à partir de plusieurs mesures Scénario : vous avez des données de précipitations (Rainfall_mm) et d’évaporation (Evaporation_mm), et vous voulez calculer le bilan hydrique net (Net Water Balance) pour chaque enregistrement.

   Rainfall_mm  Evaporation_mm  Net_Water_Balance
0          100              60                 40
1           80              70                 10
2          120              65                 55

Dans cet exemple, lambda row: row['Rainfall_mm'] - row['Evaporation_mm'] calcule le bilan hydrique net en soustrayant l’évaporation des précipitations pour chaque enregistrement.

1.5 Avancé : manipuler des séries temporelles avec des fonctions lambda

Les géoscientifiques travaillent fréquemment avec des séries temporelles (données climatiques, par exemple). Les fonctions lambda permettent des transformations de données efficaces au sein des séries temporelles.

Exemple 4 : appliquer un calcul en fenêtre glissante Scénario : supposons que vous disposez de températures journalières et que vous voulez calculer une moyenne glissante sur 3 jours.

Loading...

Ici, lambda x: x.mean() calcule la moyenne glissante sur une fenêtre de 3 jours pour des données de température, une opération essentielle en analyse climatique pour lisser les fluctuations de court terme.

1.6 Fonction d’agrégation

La méthode agg est une méthode puissante de Pandas qui permet d’effectuer plusieurs opérations sur des DataFrames et des Series. Vous pouvez appliquer une ou plusieurs fonctions d’agrégation telles que sum, mean, min, max, etc., sur différentes colonnes ou différents groupes de données.

sum     10.0
mean     2.5
Name: A, dtype: float64
Agréger plusieurs colonnes avec plusieurs fonctions

Vous pouvez passer à agg un dictionnaire dont les clés sont des noms de colonnes et les valeurs les fonctions à appliquer.

         A    B
sum   10.0  NaN
mean   2.5  NaN
min    NaN  5.0
max    NaN  8.0

Dans cet exemple, la colonne ‘A’ reçoit sum et mean, tandis que la colonne ‘B’ reçoit min et max.

Vous pouvez aussi utiliser des fonctions personnalisées

              A    B
mean        2.5  NaN
data_range  3.0  3.0

2 Cartographier avec Plotly

Nous allons maintenant tracer la position des séismes sur une carte avec le paquet Plotly. Plus de tutoriels sur Plotly. Les arguments de la fonction sont explicites et typiques des fonctions Python. La documentation de scatter_geo de Plotly liste les variables.

Loading...

La fonction lambda lambda x: 'Minor' if x < 4.0 else ('Moderate' if x < 6.5 else 'Severe') classe les magnitudes de séismes selon leurs valeurs.

Les données étaient triées par date. Nous voulons maintenant trier et afficher les données par magnitude. Nous utilisons la fonction pandas sort pour créer un nouveau DataFrame aux valeurs triées.

Loading...

Traçons de nouveau avec Plotly

Loading...

3 Créer un DataFrame pandas depuis un fichier texte générique

Le paquet Python pandas est très utile pour lire des fichiers csv, mais aussi de nombreux fichiers texte plus ou moins formatés en une observation par ligne et une colonne par caractéristique (feature).

À titre d’exemple, nous allons examiner la liste des stations sismiques du réseau sismique de Californie du Nord, disponible ici :

Regardons les données. Elles sont maintenant stockées dans un DataFrame pandas.

Loading...

Nous pouvons afficher le premier élément du DataFrame :

station AAR network NC channel EHZ location -- rate 0.0 start_time 1976/07/20,17:38:00 end_time 1977/12/01,22:37:00 latitude 39.27594 longitude -121.02696 elevation 911.0 depth 0.0 dip -90.0 azimuth 0.0 Name: 0, dtype: object
station str network str channel str location str rate float64 start_time str end_time str latitude float64 longitude float64 elevation float64 depth float64 dip float64 azimuth float64 dtype: object
0 AAR 1 AAR 2 AAR 3 AAR 4 AAR ... 33375 WMP 33376 WMP 33377 WMP 33378 WSL 33379 WWVB Name: station, Length: 33380, dtype: str

Les colonnes start_time et end_time sont stockées comme object (chaînes de caractères) : nous ne pouvons donc pas encore faire d’arithmétique de dates dessus. Nous les convertissons avec pd.to_datetime et une chaîne de format explicite.

Une mise en garde sur les assistants IA : un assistant IA peut échouer sur cette conversion si vous lui donnez un prompt (une consigne) vague, par exemple en devinant la mauvaise chaîne de format ou en écartant silencieusement les dates hors plage. Vérifiez toujours dtypes (et quelques valeurs réelles) après tout code d’interprétation écrit par une IA.

Les dates de fin demandent une étape de plus. Le NCEDC marque les canaux encore en service avec la date de fin fictive 3000/01/01. Ce n’est pas une vraie date de fin. Nous passons errors='coerce' pour que toute entrée non interprétable devienne NaT (not-a-time) au lieu de lever une erreur ; sur les versions plus anciennes de pandas, qui stockaient les horodatages à la résolution de la nanoseconde, l’an 3000 était hors plage et se faisait convertir ainsi. Pandas 3 interprète les horodatages à la résolution de la microseconde : l’an 3000 se lit donc désormais sans problème, et nous mettons explicitement la valeur fictive à NaT. C’est délibéré et porteur de sens : après la conversion, NaT dans end_time identifie les canaux encore en fonctionnement.

Loading...
station                  str
network                  str
channel                  str
location                 str
rate                 float64
start_time    datetime64[us]
end_time      datetime64[us]
latitude             float64
longitude            float64
elevation            float64
depth                float64
dip                  float64
azimuth              float64
dtype: object
still-operating channels (NaT end_time): 5619

Utilisez Plotly pour cartographier les stations. Nous écartons les lignes sans coordonnées et gardons les dates de fin NaT, puisqu’elles portent de l’information.

Loading...
Loading...

4 Exercice

Nous allons maintenant nous exercer à manipuler pandas. Cet exercice récupère des métadonnées de stations depuis une URL, et les étudiants s’exercent sur des tâches précises.

Téléchargez les données depuis l’URL du NCEDC

Les noms de colonnes figurent en tête du fichier texte ; faites-en une liste de chaînes de caractères, dans l’ordre, afin de renommer les colonnes une fois le DataFrame créé

Trouvez la ligne du canal KCPB

Sélectionnez maintenant deux stations de votre choix à l’aide de |.

Sélectionnez maintenant une station donnée et un code de canal précis, par exemple KCPB et le code de canal HNZ.

Vous pouvez aussi choisir la fonction pandas isin pour sélectionner les lignes dont un attribut donné appartient à une liste. Par exemple, utilisez isin pour sélectionner toutes les lignes dont la clé station figure dans une liste ['KCPB','KHBB'].

Q Utilisez les fonctions natives de pandas pour calculer le nombre de sites uniques (noms de stations) dans le réseau.

Q Utilisez les fonctions natives de pandas pour sélectionner l’ensemble unique des codes de canaux qui se terminent par Z : cela vous dira combien de types de données numérisées le réseau sismique gère.

Q Quel nom de station compte le plus grand nombre de canaux ? indice : vous pouvez utiliser value_counts().

Q Quelle est la différence d’altitude maximale entre les stations, en utilisant des fonctions lambda

Ici, pandas ne reconnaît pas les colonnes start_time et end_time comme un format datetime, nous ne pouvons donc pas leur appliquer d’opérations de dates. Il faut d’abord convertir ces colonnes en format datetime :

Nous pouvons maintenant regarder quand chaque station sismique a été installée, avec groupby et un tri par déploiement le plus ancien (c’est-à-dire le minimum de start_time)

Sélectionnez les stations déployées en premier et récupérées en dernier avec agg et des fonctions lambda

5 CSV vs Parquet

Parquet est un format de données compressé qui stocke et compresse les colonnes. Il est rapide en entrées-sorties et compact.

Sauvegardez data dans un fichier CSV :

135 ms ± 4.59 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
-rw-r--r--@ 1 marinedenolle  staff   3.2M Aug 12 09:28 data/my_metadata.csv

Essayez de sauvegarder en Parquet et comparez le temps et la mémoire.

11.1 ms ± 253 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)
-rw-r--r--@ 1 marinedenolle  staff   338K Aug 12 09:28 data/my_metadata.pq