Pandas est un package python qui permet de traiter des jeux de données de manière efficace et compréhensible. De la lecture des fichiers à une première approche statistique.
Pandas est le compagnon de jeu de n’importe quel datascientist pythonicien ! Pandas est souvent accompagné de son ami scikit learn, LE package de machine learning de python. Avant de pouvoir utiliser scikit learn, Pandas intervient dans la première phase d’un projet de datascience, afin de lire, comprendre et préparer la donnée.
Nous
vous proposons, à travers un exemple, de passer en revue les principales
fonctionnalités de ce package, en suivant les grandes étapes du datamanagement.
Nous allons nous intéresser à l’historique des prénoms de 2004 à 2017 dans l’agglomération parisienne. Et pour les plus bretons d’entre nous, nous étudierons aussi les prénoms rennais. Ces deux datasets nous permettront d’apprendre à utiliser Pandas.
Les
plus courageux pourront utiliser le dataset final pour prédire les prénoms les
plus populaires dans les années suivantes et, surtout, choisir le prénom de leur
futur enfant.
Il est important de mentionner que l’aide de Pandas est très bien documentée. Les fonctions présentées dans ce tutorial sont le plus souvent utilisées dans leur version par défaut, mais de nombreuses options supplémentaires existent et permettent de simplifier les démarches.
Comment lire et stocker mes données ?
La première étape - et parfois la plus compliquée - est de lire les données. Pandas simplifie la lecture de fichiers de tout type : csv, xlsx, txt, json ou encore d’un dictionnaire python. Les données lues sont stockées dans des dataframes.
Un dataframe est une structure de données permettant de stocker les données selon deux dimensions : lignes et colonnes. Les colonnes sont accessibles par les noms de colonne et les lignes sont accessibles par leur index. Ce dernier peut-être un entier, une date, une chaîne de caractères. Pandas gère également le multi-index.
Revenons à notre lecture de fichier. De multiples options permettent de gérer :
Les séparateurs
L'encodage
Le type de chaque colonne
La présence ou non d'un en-tête de colonne
La façon de traiter les valeurs manquantes
La façon de traiter les dates
Le nombre de lignes à sauter
Par
défaut, pandas interprète le type des données présentes dans chaque colonne en
lisant les premières lignes du fichier. Rien ne permet de s’assurer que cette
méthode est toujours performante (allez, disons presque toujours). Il
est donc préférable de parfaitement préparer la lecture du fichier en précisant
un schéma de données (en-tête et type). Évidemment, ami pythonicien, l’ajout de
quelques try et autres except est toujours aussi indispensable.
Créer un dataframe après avoir lu les données dans une base SQL, PostgreSQL, Mongo ou tout autre système d’informations est aussi tout à fait possible. En fonction des différents SI, des packages et des drivers additionnelles doivent être installés. Il faut donc utiliser différentes fonctions pour obtenir un dataframe à partir de listes, de dictionnaires, etc. Passons tout de suite à la pratique :
Pour le fichier CSV :
Pour le fichier json :
Si le fichier est trop gros, l'option chunksize permet de lire le fichier en plusieurs fois pour ensuite les concaténer dans un dataframe :
Explorer mon dataframe
Une fois le fichier lu, il est temps de passer à une première analyse de ces données. Nul besoin d’un autre package, pandas s’occupe de tout.
Afficher un échantillon du dataframe
Généralement, on préfère ne pas afficher le dataframe en entier. On se contentera d’afficher juste un sous ensemble du dataframe en utilisant la fonction head (ou tail par symétrie).
df_paris.head() par défaut retourne les 5 premières lignes.
Filtrer sur une valeur spécifique
Si je veux afficher que les lignes contenant mon prénom :
df_paris [ df_paris [‘Prenoms’]==’Dora’ ] ff
Prenons deux minutes pour comprendre ce que fait Pandas :
Pour chaque ligne du dataframe, l'expression entre les crochets est évaluée pour retourner un booléen.
Seules lignes avec valeur égale à True sont affichées.
On atteint le résultat suivant :
Description du dataframe
Après avoir affiché notre dataframe, on passe à l'analyse de son contenu :
Nombre de lignes
Type de colonnes
Valeurs possibles pour chaque colonne
Le nombre de lignes est obtenu en utilisant shape : df_paris.shape qui retourne le nombre de lignes et colonnes de notre dataframe. Nous obtenons le type de chaque colonne en utilisant dtypes.
On obtient le résultat suivant :
Les
colonnes 'Sexe' et 'Prenoms' sont des objets et les colonne 'Annee' et 'Nombre'
sont des entiers. Afin
d’éviter les éventuels conflits, nous voulons que les valeurs de la colonne
‘Annee’ soient de type str. Pour
cela, nous utilisons la fonction astype avec le type voulu en paramètre :
Nous
pouvons pour chaque colonne obtenir un résumé des données présentes en
utilisant la fonction describe() (le
nombre de valeurs, la moyenne, l’écart type, le minimum, le maximum et des
quantiles). Évidemment,
cette fonction ne s’applique que sur les colonnes numériques.
Pour obtenir des informations sur toutes les colonnes, l’option include=’all’ est disponible :
Cette fonction nous permet de découvrir qu’il existe dans le dataset, 2 389 prénoms différents pour des années de 2004 à 2007.
Renommer une colonne
Afin de faciliter la lecture des données par nos amis anglais, nous pouvons aussi renommer une ou plusieurs colonnes en créant un dictionnaire de correspondance avec l’aide de la fonction (attention surprise) rename
Pour la première fois, une option très importante vient de faire son apparition. L’argument inplace permet de préciser si on veut appliquer sur le dataframe lui-même (inplace = True) ou sur une copie du dataframe (inplace = False). Les deux lignes suivantes sont équivalentes :
Gérer les lignes en double
Une étape importante dans l’exploration de nos données est la suppression des lignes dupliquées via la méthode drop_duplicates. Celle-ci retourne un dataframe avec les lignes en double supprimées, avec possibilité de considérer seulement certaines colonnes. Elle prend en argument :
Subset : Liste des colonnes sur lesquelles on va vérifier l’existence de lignes en double
Option keep qui a trois valeurs possibles : ‘first’ : garder la première occurrence, ‘last’ garder la dernière occurrence et 'False' pour supprimer toutes les occurrences
Pour notre cas, nous voulons vérifier sur toutes les colonnes et garder la première occurrence :
Gérer les valeurs inconnues
On observe que la colonne 'Sexe' possède trois valeurs distinctes : F, M et X. La valeur ‘X’ peut avoir plusieurs significations : une valeur manquante, une valeur indéterminée ou même les prénoms qui sont à la fois masculin et féminin. Dans un monde idéal, il faudrait contacter le responsable de l’extraction pour obtenir cette information. Ici, nous ne pouvons effectuer cette démarche, donc nous allons enquêter par nos propres moyens :
On filtre sur les lignes où les valeurs ‘Sexe’ == ‘X’
Ensuite, on récupère la colonne ‘Prenoms ‘ :
Puis, on récupère la liste des prénoms distincts :
Ainsi, on peut concaténer les étapes a, b et c en une seule ligne :
On obtient les prénoms suivants :
Au vu des prénoms affichés, l’hypothèse principale est que ce X représente en fait une valeur manquante. Nous choisissons donc de filtrer ces lignes.
Encore plus d'options
Pour faciliter la lecture des données, il est parfois utile de ranger les valeurs d’une colonne. ff00000000
On observe que sur les 11 premières lignes, on retrouve 9 Gabriel et 2 Adam surtout sur les dernières années. Dans le top 15, on retrouve un seul prénom féminin. Pour étudier une seule colonne ou quelques valeurs, de nombreuses possibilités sont à notre disposition :
Une colonne : df['Annee'] L
Quelques lignes : df[0:3]
Pour obtenir toutes les valeurs de la ligne 3 : df.iloc[3]
Pour obtenir la valeur de la colonne A correspondant à une valeur particulière : df.loc[dates[0],'A']
Attention à ne pas confondre : loc et iloc !
Modifier mon dataframe
Gérer les valeurs manquantes
Une problématique, d’une grande importance pour les data scientists, est la gestion des valeurs manquantes. La méthode la plus simple, mais rarement la plus efficace, est d’enlever toutes les lignes ayant au moins une valeur manquante :
Il est tout aussi facile de remplacer les valeurs manquantes par une valeur fixe ou par une valeur moyenne :
Créer une nouvelle colonne
On entend souvent que les prénoms courts sont à la mode. Nous nous proposons de vérifier cette assertion. Pour cela, nous allons créer une nouvelle colonne grâce à une des nombreuses méthodes possibles. En utilisant le concept de list comprehension, on peut créer une colonne de la façon suivante :
Ceci
nous permet de trouver un prénom de deux lettres : El qui est donné
régulièrement ces dernières années.
On peut choisir de créer une nouvelle règle basée sur des règles de gestion. Nous proposons une toute première approche pour estimer le sexe d’un basé sur la dernière lettre du prénom ou la longueur du prénom. Le package numpy peut aussi être utile avec sa fonction where :
Modifier une colonne
Il peut être utile aussi de ‘recoder’ une colonne. Souvent, il existe de multiples valeurs correspondantes à la même occurrence (exemple : H pour Homme).
Ici on transforme le ‘M’ en masculin et le ‘F’ en Féminin
Ne pas oublier de checker si la colonne "Sexe" ne présente pas d'autres valeurs qu'on aurait oublié de traiter. On peut même appliquer une fonction custom et l’appliquer à une colonne de notre dataframe :
Filtrer des lignes
On peut utiliser des méthodes pandas ou des méthodes plus pythoniques :
L’avantage des deux dernières est qu’elles permettent de chainer un grand nombre de lignes de codes pour rendre le code plus compact.
Groupby
Pour finir ce chapitre, il nous reste à vous présenter le groupby qui fonctionne de la même façon que le groupby en SQL. Si on veut sommer les prénoms donnés sur toutes les années, on regroupe par nom et on somme sur le nombre :
NB : en sortie du groupby, nous obtenons un multi index, il faut donc utiliser la fonction reset_index pour transformer le multi-index en colonne.
Si on oublie l’option reset_index , on obtient le résultat suivant :
Les colonnes ‘Firstname’ et ‘Number’ sont passées en index.
Revenons
à notre groupby. Nous obtenons les prénoms les plus données depuis 2004 dans
Paris. Les vainqueurs sont Louise et Emma pour les filles et Gabriel et Raphaël
pour les garçons. Nous
remarquons que le prénom Camille est aussi dans le top 10 des prénoms les plus
données. [SV1]
Vous pouvez ajouter la colonne ‘Sex’ au groupby pour avoir les top prénoms féminins et masculins.
Les valeurs NA ne sont pas toujours à supprimer, tout dépend de leurs significations et de ce qu'on veut faire avec le dataframe.
Faire attention aux indexes lorsqu'on effectue des transformations sur notre dataframe
Joindre plusieurs dataframes
En datamanagement, une des actions les plus courantes est de joindre plusieurs tables pour regrouper les données en un seul dataframe. Nous avons à notre disposition un second dataframe, l’équivalent du premier, mais avec les prénoms donnés dans la ville de Rennes. Avant de pouvoir joindre ces deux dataframes, nous devons unifier les différentes colonnes.
Nous pouvons maintenant joindre ces fichiers :
Nous avons deux colonnes qui portent le même nom ‘Number’ mais qui n’a pas été utilisé pour la jointure. Après la jointure, nous récupérons alors deux colonnes ‘Number_x’ et ‘Number_y’. Pour éviter les confusions, nous devons renommer les colonnes avant la jointure.
Nous retrouvons les mêmes prénoms dans les
tops prénoms pour la ville de Rennes. Evidemment, les valeurs dans la colonne
NumberRennes sont plus petites que pour Paris. On peut imaginer trouver un indicateur permettant de renormaliser ces valeurs permettant de les comparer.[SV1]
Les différentes possibilités pour l’argument how sont :
Left : toutes les lignes du dataframe de gauche sont gardés auxquels sont rajoutés les informations du dataframe de droite
Right : symétrique à left
Outer : garde toutes les lignes des deux dataframes
Inner : gardes uniquement les lignes communs dans les deux dataframes
Pour conclure, nous pouvons chercher les prénoms les plus données sans avoir été donnée dans l’autre ville :
Pivoter un dataframe
Pandas vous permet également de transformer (reshapping) votre dataframe. Pivoter les colonnes en lignes, ou inversement, les lignes en colonnes, se fait avec deux fonctions qui fonctionnent de manière symétrique : pivot et melt.
La fonction pivot
La fonction pivot prend trois arguments qui déterminent la façon dont le dataframe va pivoter :
Values : les valeurs du dataframe original que vous voulez voir dans la table pivot.
Columns : cet argument permet de spécifier ce qui deviendra la colonne dans la table pivot.
Index : cet argument permet de spécifier ce qui deviendra l'index dans la table pivot.
Afin de mieux évaluer les tendances annuelles et l’évolution du choix des prénoms, nous pouvons utiliser cette fonction pour pivoter notre dataframe