Utilisation de la bibliothèque pandas
⚓︎
Source : fiche éduscol sur le Manipulation de tables avec la bibliothèque Pandas
La bibliothèque pandas
va nous permettre de faire des traitements sur les tables CSV plus complexes qu'avec la bibliothèque csv
.
Ce document, nous montre les rudiments de la bibliothèque pandas
puis nous montre comment mettre en relation
les tables countries.csv et cities.csv (fusion de deux tables).
Prise en main⚓︎
Lecture de fichiers⚓︎
La lecture d’un fichier csv se fait alors aisément grâce à la commande pandas.read_csv
1
🐍 Script Python | |
---|---|
1 2 3 |
|
Le fichier countries.csv
est le même que dans le chapitre précédent, explorons un peu l’autre à l'aide des commandes de pandas
.
🐍 Script Python | |
---|---|
1 2 3 4 |
|
>>> villes.dtypes
id int64
name object
latitude float64
longitude float64
country object
population int64
dtype: object
On peut aussi avoir des données statistiques (bien sûr, seules celles concernant la population soient pertinentes) :
>>> villes.describe()
id latitude longitude population
count 4.958600e+04 49586.000000 49586.000000 4.958600e+04
mean 2.906145e+06 29.814778 7.495539 6.002666e+04
std 1.949404e+06 23.827507 70.496206 3.358441e+05
min 1.057000e+04 -54.810840 -178.158330 0.000000e+00
25% 1.283615e+06 17.954320 -57.055248 7.838250e+03
50% 2.811052e+06 38.415305 10.006785 1.451550e+04
75% 3.652341e+06 47.380827 45.522797 3.463750e+04
max 1.210423e+07 78.223340 179.364510 2.231547e+07
Enfin, on peut facilement ne conserver que les champs qui nous intéressent. Par exemple, si l’on ne veut que les noms des villes et leurs coordonnées, on utilise :
>>> villes[['name', 'latitude', 'longitude']]
Dataframes et series⚓︎
Les tables lues dans les fichiers csv sont stockés par pandas
sous forme de dataframes
. On peut les voir comme un tableau
de p-uplets nommés. Par exemple, l’enregistrement numéro 10 (obtenu grâce à la méthode loc
) s’obtient en exécutant :
>>> villes.loc[10]
id 291580
name Zayed City
latitude 23.6542
longitude 53.7052
country AE
population 63482
Name: 10, dtype: object
et son nom s’obtient comme pour un dictionnaire :
>>> villes.loc[10]['name']
'Zayed City'
Une série est ce que l’on obtient à partir d’un dataframe
en ne sélectionnant qu’un seul champ.
>>> villes['name']
0 Sant Julià de Lòria
1 Ordino
2 les Escaldes
...
49697 Epworth
49698 Chitungwiza
Name: name, Length: 49586, dtype: object
>>> type(villes['name'])
<class 'pandas.core.series.Series'>
Lors de la sélection d’un unique champ, pandas
permet d’utiliser une syntaxe légère en n’écrivant que villes.name
plutôt que
villes['name']
.
Il convient, pour finir, de différentier :
- la serie villes['name']
(ou ville.name
, donc) et
- le dataframe à un seul champ villes[['name']]
.
Interrogations simples⚓︎
On veut connaître le noms des pays où l’on paye en euros.
On sélectionne la bonne valeur de currency_code
ainsi :
>>> pays[pays.currency_code == 'EUR']
>>> pays[pays.currency_code == 'EUR'].name
On veut connaître les codes des monnaies appelées Dollar
. On peut écrire :
>>> pays[pays.currency_name == 'Dollar'].currency_code.unique()
unique
s’applique à une série et non un dataframe.
Tris⚓︎
Les méthodes nlargest
et nsmallest
permettent de déterminer les plus grands et plus petits éléments selon un critère
donné. Ainsi, pour obtenir les pays les plus grands en superficie et ceux les moins peuplés, on peut écrire :
>>> pays.nlargest(10, 'area')
>>> pays.nsmallest(10, 'population')
sort_values
, comme par exemple :>>> villes.sort_values(by='population')
>>> pays.sort_values(by=['continent', 'area'], ascending=[True, False])[['continent', 'name', 'area']]
continent name area
3 AF Algeria 2381740.0
58 AF Democratic Republic of the Congo 2345410.0
213 AF Sudan 1861484.0
.. ... ... ...
214 SA Suriname 163270.0
76 SA French Guiana 91000.0
71 SA Falkland Islands 12173.0
[251 rows x 3 columns]
Manipulation de données⚓︎
Création d'un champs⚓︎
Il est très facile de créer de nouveaux champs à partir de champs existants. Par exemple, pour calculer la densité de chaque pays, il suffit
d’exécuter :
>>> pays['density'] = pays.population / pays.area
Fusion de tables⚓︎
Dans la table des pays, la capitale est indiquée par un numéro unique, dans le champ capital
, qui correspond au champ id
de la table des villes.
Pour récupérer le nom de la capitale de chaque pays, nous allons fusionner les tables en effectuant une jointure.
Ainsi, nous allons faire correspondre le champ capital
de pays et le champ id
de villes. Cela se fait à l’aide de la fonction merge
:
>>> pandas.merge(pays, villes, left_on='capital', right_on='id')
Cependant, en procédant ainsi, il va y avoir un conflit entre les champs des deux tables. Cela apparaît en listant les champs de la table obtenue :
>>> pandas.merge(pays, villes, left_on='capital', right_on='id').columns
Index(['iso', 'name_x', 'capital', 'area', 'population_x', 'continent',
'currency_code', 'currency_name', 'density', 'id', 'name_y', 'latitude',
'longitude', 'country', 'population_y'],
dtype='object')
name
et population
, d’où les suffixes _x
et _y
pour
marquer la référence à la première table ou à la seconde.
Pour rendre cela plus lisible, nous allons :
- ne garder que les colonnes de ville
qui nous intéressent, ici l’identifiant et le nom ;
- renommer ces colonnes pour éviter les collisions avec les champs de pays :
>>> villes[['id', 'name']].rename(columns={'id': 'capital', 'name': 'capital_name'})
capital capital_name
0 3039163 Sant Julià de Lòria
1 3039678 Ordino
2 3040051 les Escaldes
... ... ...
49583 895417 Banket
49584 1085510 Epworth
49585 1106542 Chitungwiza
[49586 rows x 2 columns]
Et c’est cette nouvelle table que nous allons fusionner avec la table pays (dont nous ne garderons pas toutes les colonnes non
plus) :
>>> pays_et_capitales = pandas.merge(
... pays[['iso', 'name', 'capital', 'continent']],
... villes[['id', 'name']].rename(
... columns={'id': 'capital', 'name': 'capital_name'}),
... on='capital')
>>> pays_et_capitales[pays_et_capitales.continent == 'OC']
Conclusion⚓︎
La bibliothèque pandas permet d'exploiter facilement des données organisées en table. En particulier, le rôle central qu’y jouent les dataframes permet de manipuler les enregistrements quasiment comme s’il s’agissait de p-uplet nommés.
Cette approche permet aussi de préparer la transition avec le programme de Terminale et le chapitre sur les bases de données.
En effet, bien que ce thème apporte des problématiques spécifiques, et bien que les syntaxes diffèrent grandement entre des
instructions pandas
et une requête SQL
, il existe de nombreux points communs entre les deux approches concernant la façon
dont les données sont représentées et peuvent être exploitées et manipulées.
-
L’option keep_default_na=False est nécessaire à cause de la gestion des données manquantes. Une absence est parfois précisée spécifiquement en écrivant NA plutôt que de ne rien mettre. Ainsi, à la base, la lecture de NA est interprété comme une donnée manquante. On est obligé de désactiver ce traîtement de base pour pouvoir utiliser NA comme tel, comme code de l’Amérique du Nord. ↩