Recherche de site Web

Analyse de données et visualisation avec pandas et Jupyter Notebook en Python 3


Introduction

Le package pandas de Python est utilisé pour la manipulation et l'analyse des données, conçu pour vous permettre de travailler avec des données étiquetées ou relationnelles de manière intuitive.

Le package pandas offre des fonctionnalités de feuille de calcul, mais parce que vous travaillez avec Python, il est beaucoup plus rapide et plus efficace qu'un programme de feuille de calcul graphique traditionnel.

Dans ce tutoriel, nous allons passer en revue la mise en place d'un ensemble de données volumineux avec lequel travailler, les fonctions groupby() et pivot_table() de pandas, et enfin comment visualiser les données.

Pour se familiariser avec le package pandas, vous pouvez lire notre tutoriel Une introduction au package pandas et à ses structures de données en Python 3.

Conditions préalables

Ce guide couvrira comment travailler avec des données dans pandas sur un ordinateur local ou un serveur distant. Travailler avec de grands ensembles de données peut être gourmand en mémoire, donc dans les deux cas, l'ordinateur aura besoin d'au moins 2 Go de mémoire pour effectuer certains des calculs dans ce guide.

Pour ce tutoriel, nous utiliserons Jupyter Notebook pour travailler avec les données. Si vous ne l'avez pas encore, vous devriez suivre notre tutoriel pour installer et configurer Jupyter Notebook pour Python 3.

Configuration des données

Pour ce tutoriel, nous allons travailler avec les données de la Sécurité Sociale des États-Unis sur les prénoms de bébés qui sont disponibles sur le site de la Sécurité Sociale sous la forme d'un fichier zip de 8 Mo.

Activons notre environnement de programmation Python 3 sur notre machine locale ou sur notre serveur à partir du répertoire correct :

  1. cd environments
  1. . my_env/bin/activate

Maintenant, créons un nouveau répertoire pour notre projet. Nous pouvons l'appeler noms puis nous déplacer dans le répertoire :

  1. mkdir names
  2. cd names

Dans ce répertoire, nous pouvons télécharger le fichier zip depuis le site Web de la Sécurité Sociale avec la commande curl :

  1. curl -O https://www.ssa.gov/oact/babynames/names.zip

Une fois le fichier téléchargé, vérifions que nous avons tous les paquets installés que nous allons utiliser :

  • numpy pour prendre en charge des tableaux multi-dimensionnels
  • matplotlib pour visualiser des données
  • pandas pour notre analyse de données
  • seaborn pour rendre nos graphiques statistiques matplotlib plus esthétiques.

Si vous n'avez aucun des paquets déjà installés, installez-les avec pip, comme suit :

  1. pip install pandas
  2. pip install matplotlib
  3. pip install seaborn

Le package numpy sera également installé si vous ne l'avez pas déjà.

Maintenant, nous pouvons démarrer Jupyter Notebook :

  1. jupyter notebook

Une fois que vous êtes sur l'interface Web de Jupyter Notebook, vous verrez le fichier names.zip là-bas.

Pour créer un nouveau fichier de carnet, sélectionnez Nouveau > Python 3 dans le menu déroulant en haut à droite :

Cela ouvrira un carnet.

Commençons par importer les paquets que nous allons utiliser. En haut de notre carnet, nous devrions écrire ce qui suit :

import numpy as np
import matplotlib.pyplot as pp
import pandas as pd
import seaborn

Nous pouvons exécuter ce code et passer à un nouveau bloc de code en tapant ALT + ENTER.

Disons aussi à Python Notebook de garder nos graphiques en ligne :

matplotlib inline

Exécutons le code et continuons en tapant ALT + ENTER.

À partir de là, nous allons décompresser l'archive zip, charger le jeu de données CSV dans pandas, puis concaténer les DataFrames pandas.

Décompresser l'archive Zip

Pour décompresser l'archive zip dans le répertoire actuel, nous allons importer le module zipfile puis appeler la fonction ZipFile avec le nom du fichier (dans notre cas names.zip):

import zipfile
zipfile.ZipFile('names.zip').extractall('.')

Nous pouvons exécuter le code et continuer en tapant ALT + ENTER.

Maintenant, si vous regardez dans votre répertoire noms, vous aurez des fichiers .txt contenant des données de noms au format CSV. Ces fichiers correspondront aux années de données en fichier, de 1881 à 2015. Chacun de ces fichiers suit une convention de nommage similaire. Le fichier de 2015, par exemple, s'appelle yob2015.txt, tandis que le fichier de 1927 s'appelle yob1927.txt.

Pour regarder le format de l'un de ces fichiers, utilisons Python pour en ouvrir un et afficher les 5 premières lignes :

open('yob2015.txt','r').readlines()[:5]

Exécutez le code et continuez avec ALT + ENTER.

['Emma,F,20355\n',
 'Olivia,F,19553\n',
 'Sophia,F,17327\n',
 'Ava,F,16286\n',
 'Isabella,F,15504\n']

La façon dont les données sont formatées est d'abord le nom (comme dans Emma ou Olivia), ensuite le sexe (comme F pour le prénom féminin et M pour le prénom masculin), puis le nombre de bébés nés cette année-là portant ce prénom (il y avait 20 355 bébés nommés Emma nés en 2015).

Avec ces informations, nous pouvons charger les données dans pandas.

Charger les données CSV dans pandas

Pour charger des données au format valeurs séparées par des virgules dans pandas, nous utiliserons la fonction pd.read_csv(), en passant le nom du fichier texte ainsi que les noms des colonnes que nous décidons. Nous le stockerons dans une variable, dans ce cas names2015, puisque nous utilisons les données du fichier de l'année de naissance 2015.

names2015 = pd.read_csv('yob2015.txt', names = ['Name', 'Sex', 'Babies'])

Tapez ALT + ENTER pour exécuter le code et continuer.

Pour s'assurer que cela a fonctionné, affichons le haut de la table :

names2015.head()

Lorsque nous exécutons le code et continuons avec ALT + ENTER, nous verrons une sortie qui ressemble à ceci :

Notre tableau contient maintenant des informations sur les noms, le sexe et le nombre de bébés nés avec chaque nom organisés par colonne.

Concaténer des objets pandas

Concaténer des objets pandas nous permettra de travailler avec tous les fichiers texte séparés dans le répertoire noms.

Pour concaténer cela, nous devrons d'abord initialiser une liste en assignant une variable à un type de données liste non peuplée :

all_years = []

Une fois que nous aurons fait cela, nous utiliserons une boucle for pour itérer sur tous les fichiers par année, qui vont de 1880 à 2015. Nous ajouterons +1 à la fin de 2015 afin que 2015 soit inclus dans la boucle.

all_years = []

for year in range(1880, 2015+1):

Dans la boucle, nous ajouterons à la liste chacune des valeurs du fichier texte, en utilisant un formatteur de chaîne pour gérer les différents noms de chacun de ces fichiers. Nous passerons ces valeurs à la variable year. Encore une fois, nous spécifierons les colonnes pour Name, Sex et le nombre de Babies :

all_years = []

for year in range(1880, 2015+1):
    all_years.append(pd.read_csv('yob{}.txt'.format(year),
                                 names = ['Name', 'Sex', 'Babies']))

De plus, nous allons créer une colonne pour chacune des années afin de les garder ordonnées. Nous pourrons le faire après chaque itération en utilisant l'index de -1 pour y faire référence au fur et à mesure que la boucle progresse.

all_years = []

for year in range(1880, 2015+1):
    all_years.append(pd.read_csv('yob{}.txt'.format(year),
                                 names = ['Name', 'Sex', 'Babies']))
    all_years[-1]['Year'] = year

Enfin, nous l'ajouterons à l'objet pandas par concaténation en utilisant la fonction pd.concat(). Nous utiliserons la variable all_names pour stocker ces informations.

all_years = []

for year in range(1880, 2015+1):
    all_years.append(pd.read_csv('yob{}.txt'.format(year),
                                 names = ['Name', 'Sex', 'Babies']))
    all_years[-1]['Year'] = year

all_names = pd.concat(all_years)

Nous pouvons exécuter la boucle maintenant avec ALT + ENTER, puis inspecter le résultat en appelant la fin (les lignes les plus basses) de la table résultante :

all_names.tail()

Notre ensemble de données est maintenant complet et prêt pour effectuer des travaux supplémentaires avec pandas.

Regroupement des données

Avec pandas, vous pouvez regrouper des données par colonnes avec la fonction .groupby(). En utilisant notre variable all_names pour notre ensemble de données complet, nous pouvons utiliser groupby() pour diviser les données en différentes catégories.

Regroupons le jeu de données par sexe et par année. Nous pouvons le configurer comme suit :

group_name = all_names.groupby(['Sex', 'Year'])

Nous pouvons exécuter le code et continuer avec ALT + ENTER.

À ce stade, si nous appelons simplement la variable group_name, nous obtiendrons cette sortie :

<pandas.core.groupby.DataFrameGroupBy object at 0x1187b82e8>

Cela nous montre qu'il s'agit d'un objet DataFrameGroupBy. Cet objet contient des instructions sur la façon de regrouper les données, mais il ne donne pas d'instructions sur la façon d'afficher les valeurs.

Pour afficher des valeurs, nous devrons donner des instructions. Nous pouvons calculer .size(), .mean(), et .sum(), par exemple, pour renvoyer un tableau.

Commençons par .size() :

group_name.size()

Lorsque nous exécutons le code et continuons avec ALT + ENTER, notre sortie ressemblera à ceci :

Sex  Year
F    1880      942
     1881      938
     1882     1028
     1883     1054
     1884     1172
...

Ces données semblent bonnes, mais elles pourraient être plus lisibles. Nous pouvons les rendre plus lisibles en ajoutant la fonction .unstack :

group_name.size().unstack()

Maintenant, lorsque nous exécutons le code et continuons en tapant ALT + ENTER, la sortie ressemble à ceci :

Ce que ces données nous indiquent, c'est combien de noms féminins et masculins il y avait pour chaque année. En 1889, par exemple, il y avait 1 479 noms féminins et 1 111 noms masculins. En 2015, il y avait 18 993 noms féminins et 13 959 noms masculins. Cela montre qu'il y a une plus grande diversité dans les noms au fil du temps.

Si nous voulons obtenir le nombre total de bébés nés, nous pouvons utiliser la fonction .sum(). Appliquons cela à un ensemble de données plus petit, l'ensemble names2015 provenant du fichier unique yob2015.txt que nous avons créé précédemment :

names2015.groupby(['Sex']).sum()

Tapons ALT + ENTRÉE pour exécuter le code et continuer :

Cela nous montre le nombre total de bébés de sexe masculin et féminin nés en 2015, bien que seuls les bébés dont le nom a été utilisé au moins 5 fois cette année-là soient comptés dans l'ensemble de données.

La fonction pandas .groupby() nous permet de segmenter nos données en groupes significatifs.

Tableau croisé dynamique

Les tableaux croisés dynamiques sont utiles pour résumer les données. Ils peuvent trier, compter, totaliser ou moyenner automatiquement des données stockées dans un tableau. Ensuite, ils peuvent afficher les résultats de ces actions dans un nouveau tableau de ces données résumées.

Dans pandas, la fonction pivot_table() est utilisée pour créer des tableaux croisés.

Pour construire un tableau croisé dynamique, nous allons d'abord appeler le DataFrame avec lequel nous voulons travailler, puis les données que nous souhaitons afficher, et comment elles sont groupées.

Dans cet exemple, nous allons travailler avec les données all_names et montrer les données des bébés regroupées par Nom dans une dimension et par Année dans l'autre :

pd.pivot_table(all_names, 'Babies', 'Name', 'Year')

Quand nous tapons ALT + ENTER pour exécuter le code et continuer, nous verrons la sortie suivante :

Parce que cela montre beaucoup de valeurs vides, nous pouvons vouloir garder le Nom et l'Année comme colonnes plutôt que comme lignes dans un cas et colonnes dans l'autre. Nous pouvons le faire en regroupant les données entre crochets :

pd.pivot_table(all_names, 'Babies', ['Name', 'Year'])

Une fois que nous tapons ALT + ENTER pour exécuter le code et continuer, ce tableau ne montrera désormais que les données des années qui sont enregistrées pour chaque nom :

Name       Year
Aaban      2007     5.0
           2009     6.0
           2010     9.0
           2011    11.0
           2012    11.0
           2013    14.0
           2014    16.0
           2015    15.0
Aabha      2011     7.0
           2012     5.0
           2014     9.0
           2015     7.0
Aabid      2003     5.0
Aabriella  2008     5.0
           2014     5.0
           2015     5.0

De plus, nous pouvons regrouper les données pour avoir le Nom et le Sexe comme une dimension, et l'Année de l'autre, comme suit :

pd.pivot_table(all_names, 'Babies', ['Name', 'Sex'], 'Year')

Lorsque nous exécutons le code et continuons avec ALT + ENTER, nous verrons le tableau suivant :

Les tables de correspondance nous permettent de créer de nouvelles tables à partir de tables existantes, ce qui nous permet de décider comment nous voulons que ces données soient groupées.

Visualiser les données

En utilisant pandas avec d'autres packages comme matplotlib, nous pouvons visualiser des données dans notre notebook.

Nous allons visualiser des données sur la popularité d'un nom donné au fil des ans. Pour ce faire, nous devons définir et trier des index pour retravailler les données, ce qui nous permettra de voir l'évolution de la popularité d'un nom particulier.

Le package pandas nous permet d'effectuer un indexage hiérarchique ou multiniveau, ce qui nous permet de stocker et de manipuler des données avec un nombre arbitraire de dimensions.

Nous allons indexer nos données avec des informations sur le sexe, puis le nom, puis l'année. Nous voudrons également trier l'index :

all_names_index = all_names.set_index(['Sex','Name','Year']).sort_index()

Tapez ALT + ENTER pour exécuter et continuer à notre prochaine ligne, où nous demanderons au notebook d'afficher le nouveau DataFrame indexé :

all_names_index

Exécutez le code et continuez avec ALT + ENTER, et la sortie ressemblera à ceci :

Ensuite, nous voudrons écrire une fonction qui tracera la popularité d'un nom au fil du temps. Nous appellerons la fonction name_plot et passerons sexe et nom comme ses paramètres que nous appellerons lorsque nous exécuterons la fonction.

def name_plot(sex, name):

Nous allons maintenant configurer une variable appelée data pour contenir le tableau que nous avons créé. Nous allons également utiliser la méthode loc du DataFrame pandas afin de sélectionner notre ligne en fonction de la valeur de l'index. Dans notre cas, nous voudrons que loc soit basé sur une combinaison de champs dans le MultiIndex, se référant à la fois aux données de sexe et de nom.

Écrivons cette construction dans notre fonction :

def name_plot(sex, name):
    data = all_names_index.loc[sex, name]

Enfin, nous voudrons tracer les valeurs avec matplotlib.pyplot que nous avons importé sous le nom pp. Nous allons ensuite tracer les valeurs des données de sexe et de nom par rapport à l'index, qui pour nos besoins est constitué des années.

def name_plot(sex, name):
    data = all_names_index.loc[sex, name]
    
    pp.plot(data.index, data.values)

Tapez ALT + ENTER pour exécuter et passer à la cellule suivante. Nous pouvons maintenant appeler la fonction avec le sexe et le nom de notre choix, tel que F pour un prénom féminin avec le prénom Danica.

name_plot('F', 'Danica')

Lorsque vous tapez ALT + ENTER maintenant, vous recevrez le message suivant :

Notez qu'en fonction du système que vous utilisez, vous pourriez avoir un avertissement concernant une substitution de police, mais les données seront toujours tracées correctement.

En regardant la visualisation, nous pouvons voir que le prénom féminin Danica a connu une légère hausse de popularité vers 1990 et a atteint son apogée juste avant 2010.

La fonction que nous avons créée peut être utilisée pour tracer des données de plusieurs noms, afin que nous puissions voir les tendances au fil du temps à travers différents noms.

Commençons par agrandir un peu notre graphique :

pp.figure(figsize = (18, 8))

Ensuite, créons une liste avec tous les noms que nous aimerions tracer :

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

Maintenant, nous pouvons parcourir la liste avec une boucle for et tracer les données pour chaque nom. Tout d'abord, nous allons essayer ces noms non genrés comme des noms féminins :

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

for name in names:
    name_plot('F', name)

Pour rendre ces données plus faciles à comprendre, incluons une légende :

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

for name in names:
    name_plot('F', name)
    
pp.legend(names)

Nous taperons ALT + ENTER pour exécuter le code et continuer, puis nous recevrons la sortie suivante :

Bien que chacun des noms ait lentement gagné en popularité en tant que noms féminins, le nom Jamie était extrêmement populaire comme nom féminin dans les années autour de 1980.

Traçons les mêmes noms mais cette fois-ci comme des noms masculins :

pp.figure(figsize = (18, 8))

names = ['Sammy', 'Jesse', 'Drew', 'Jamie']

for name in names:
    name_plot('M', name)
    
pp.legend(names)

Encore une fois, tapez ALT + ENTER pour exécuter le code et continuer. Le graphique ressemblera à ceci :

Ces données montrent une plus grande popularité des prénoms, Jesse étant généralement le choix le plus populaire, notamment dans les années 1980 et 1990.

À partir de là, vous pouvez continuer à jouer avec les données de noms, créer des visualisations sur différents noms et leur popularité, et créer d'autres scripts pour examiner différentes données à visualiser.

Conclusion

Ce tutoriel vous a présenté des manières de travailler avec de grands ensembles de données, depuis la configuration des données, jusqu'à le regroupement des données avec groupby() et pivot_table(), l'indexation des données avec un MultiIndex, et la visualisation des données pandas en utilisant le package matplotlib.

De nombreuses organisations et institutions fournissent des ensembles de données avec lesquels vous pouvez travailler pour continuer à apprendre sur pandas et la visualisation des données. Le gouvernement américain fournit des données via data.gov, par exemple.

Vous pouvez en savoir plus sur la visualisation des données avec matplotlib en suivant nos guides sur Comment tracer des données en Python 3 en utilisant matplotlib et Comment tracer la fréquence des mots en utilisant matplotlib avec Python 3.