Les exemples de ce TP sont visualisables sous forme de Jupyter Notebooks
:
Dans ce tutoriel Pandas
, nous allons utiliser deux sources de données :
-
Les émissions de gaz à effet de serre estimées au niveau communal par l’
ADEME
. Le jeu de données est disponible sur data.gouv et requêtable directement dans python avec cet url.pandas
offre la possibilité d’importer des données directement depuis un url. C’est l’option prise dans ce tutoriel. Si vous préfèrez, pour des raisons d’accès au réseau ou de performance, importer depuis un poste local, vous pouvez télécharger les données et changer les commandes d’import avec le chemin adéquat plutôt que l’url. -
Idéalement, on utiliserait directement les données disponibles sur le site de l’Insee mais celles-ci nécessitent un peu de travail de nettoyage qui n’entre pas dans le cadre de ce TP. Pour faciliter l’import de données Insee, il est recommandé d’utiliser le package
pynsee
qui simplifie l’accès aux données de l’Insee disponibles sur le site web insee.fr ou via des API1.
Après avoir installé la librairie pynsee
(voir l’introduction à pandas), nous suivrons les conventions habituelles dans l’import des packages :
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pynsee
import pynsee.download
Exploration de la structure des données
Commencer par importer les données de l’Ademe à l’aide du package pandas
. Vous pouvez nommer le DataFrame
obtenu df
.
df = pd.read_csv("https://koumoul.com/s/data-fair/api/v1/datasets/igt-pouvoir-de-rechauffement-global/convert", sep=",")
Pour les données de cadrage au niveau communal (source Insee), le package pynsee
facilite grandement la vie.
La liste des données disponibles est ici.
En l’occurrence, on va utiliser les données Filosofi (données de revenus) au niveau communal de 2016.
Le point d’entrée principal de la fonction pynsee
est la fonction download_file
.
Le code pour télécharger les données est le suivant :
df_city = pynsee.download.download_file("FILOSOFI_COM_2016")
Note
La fonction download_file
attend un identifiant unique
pour savoir quelle base de données aller chercher et
restructurer depuis le
site insee.fr.
Pour connaître la liste des bases disponibles, vous
pouvez utiliser la fonction meta = pynsee.get_file_list()
.
Celle-ci renvoie un DataFrame
dans lequel on peut
rechercher, par exemple grâce à une recherche
de mot clé:
meta = pynsee.get_file_list()
meta.loc[meta['label'].str.contains(r"Filosofi.*2016")]
Ici, meta['label'].str.contains(r"Filosofi.*2016")
signifie:
“pandas
trouve moi tous les labels où sont contenus les termes Filosofi et 2016.”
(.*
signifiant “peu m’importe le nombre de mots ou caractères entre”)
Exercice 1: Afficher des données
L’objectif de cet exercice est de vous amener à afficher des informations sur les données dans un bloc de code (notebook) ou dans la console
Commencer sur df
:
- Utiliser les méthodes adéquates pour les 10 premières valeurs, les 15 dernières et un échantillon aléatoire de 10 valeurs
- Tirer 5 pourcent de l’échantillon sans remise
- Ne conserver que les 10 premières lignes et tirer aléatoirement dans celles-ci pour obtenir un DataFrame de 100 données.
- Faire 100 tirages à partir des 6 premières lignes avec une probabilité de 1/2 pour la première observation et une probabilité uniforme pour les autres
- Faire la même chose sur
df_city
.
Cette première approche exploratoire donne une idée assez précise de la manière dont les données sont organisées.
On remarque ainsi une différence entre df
et df_city
quant aux valeurs manquantes :
la première base est relativement complète, la seconde comporte beaucoup de valeurs manquantes.
Autrement dit, si on désire exploiter df_city
, il faut faire attention à la variable choisie.
Exercice 2: structure des données
La première chose à vérifier est le format des données, afin d’identifier des types de variables qui ne conviennent pas
Ici, comme c’est pandas
qui a géré automatiquement les types de variables,
il y a peu de chances que les types ne soient pas adéquats mais une vérification ne fait pas de mal.
- Vérifier les types des variables.
S’assurer que les types des variables communes aux deux bases sont cohérents.
Pour les variables qui ne sont pas en type
float
alors qu’elles devraient l’être, modifier leur type.
Ensuite, on vérifie les dimensions des DataFrames
et la structure de certaines variables clés.
En l’occurrence, les variables fondamentales pour lier nos données sont les variables communales.
Ici, on a deux variables géographiques: un code commune et un nom de commune.
-
Vérifier les dimensions des DataFrames
-
Vérifier le nombre de valeurs uniques des variables géographiques dans chaque base. Les résultats apparaissent-ils cohérents ?
-
Identifier dans
df_city
les noms de communes qui correspondent à plusieurs codes communes et sélectionner leurs codes. En d’autres termes, identifier lesCODGEO
tels qu’il existe des doublons deLIBGEO
et les stocker dans un vecteurx
(conseil: faire attention à l’index dex
)
On se focalise temporairement sur les observations où le libellé comporte plus de deux codes communes différents
-
Regarder dans
df_city
ces observations -
Pour mieux y voir, réordonner la base obtenue par order alphabétique
-
Déterminer la taille moyenne (variable nombre de personnes:
NBPERSMENFISC16
) et quelques statistiques descriptives de ces données. Comparer aux mêmes statistiques sur les données où libellés et codes communes coïncident -
Vérifier les grandes villes (plus de 100 000 personnes), la proportion de villes pour lesquelles un même nom est associé à différents codes commune.
-
Vérifier dans
df_city
les villes dont le libellé est égal à Montreuil. Vérifier également celles qui contiennent le terme ‘Saint-Denis’
Ce petit exercice permet de se rassurer car les libellés dupliqués sont en fait des noms de commune identiques mais qui ne sont pas dans le même département. Il ne s’agit donc pas d’observations dupliquées. On se fiera ainsi aux codes communes, qui eux sont uniques.
Les indices
Les indices sont des éléments spéciaux d’un DataFrame puisqu’ils permettent d’identifier certaines observations. Il est tout à fait possible d’utiliser plusieurs indices, par exemple si on a des niveaux imbriqués.
Exercice 3: Les indices
A partir de l’exercice précédent, on peut se fier aux codes communes.
-
Fixer comme indice la variable de code commune dans les deux bases. Regarder le changement que cela induit sur le display du
DataFrame
-
Les deux premiers chiffres des codes communes sont le numéro de département. Créer une variable de département
dep
dansdf
et dansdf_city
-
Calculer les émissions totales par secteur pour chaque département. Mettre en log ces résultats dans un objet
df_log
. Garder 5 départements et produire unbarplot
-
Repartir de
df
. Calculer les émissions totales par département et sortir la liste des 10 principaux émetteurs de CO2 et des 5 départements les moins émetteurs. Sans faire de merge, regarder les caractéristiques de ces départements (population et niveau de vie)
Exercice 4: performance des indices
Un des intérêts des indices est qu’ils permettent des agrégations efficaces.
-
Repartir de
df
et créer une copiedf_copy = df.copy()
etdf_copy2 = df.copy()
afin de ne pas écraser le DataFramedf
-
Utiliser la variable
dep
comme indice pourdf_copy
et retirer tout index pourdf_copy2
-
Importer le module
timeit
et comparer le temps d’exécution de la somme par secteur, pour chaque département, des émissions de CO2
Restructurer les données
On présente généralement deux types de données :
- format wide: les données comportent des observations répétées, pour un même individu (ou groupe), dans des colonnes différentes
- format long: les données comportent des observations répétées, pour un même individu, dans des lignes différentes avec une colonne permettant de distinguer les niveaux d’observations
Un exemple de la distinction entre les deux peut être pris à l’ouvrage de référence d’Hadley Wickham, R for Data Science:
L’aide mémoire suivante aidera à se rappeler les fonctions à appliquer si besoin:
Le fait de passer d’un format wide au format long (ou vice-versa)
peut être extrêmement pratique car certaines fonctions sont plus adéquates sur une forme de données ou sur l’autre.
En règle générale, avec Python
comme avec R
, les formats long sont souvent préférables.
Exercice 5: Restructurer les données: wide to long
-
Créer une copie des données de l’
ADEME
en faisantdf_wide = df.copy()
-
Restructurer les données au format long pour avoir des données d’émissions par secteur en gardant comme niveau d’analyse la commune (attention aux autres variables identifiantes).
-
Faire la somme par secteur et représenter graphiquement
-
Garder, pour chaque département, le secteur le plus polluant
Exercice 6: long to wide
Cette transformation est moins fréquente car appliquer des fonctions par groupe, comme nous le verrons par la suite, est très simple.
-
Repartir de `df_wide = df.copy()
-
Reconstruire le DataFrame, au format long, des données d’émissions par secteur en gardant comme niveau d’analyse la commune puis faire la somme par département et secteur
-
Passer au format wide pour avoir une ligne par secteur et une colonne par département
-
Calculer, pour chaque secteur, la place du département dans la hiérarchie des émissions nationales
-
A partir de là, en déduire le rang médian de chaque département dans la hiérarchie des émissions et regarder les 10 plus mauvais élèves, selon ce critère.
Combiner les données
Une information que l’on cherche à obtenir s’obtient de moins en moins à partir d’une unique base de données. Il devient commun de devoir combiner des données issues de sources différentes. Nous allons ici nous focaliser sur le cas le plus favorable qui est la situation où une information permet d’apparier de manière exacte deux bases de données (autrement nous serions dans une situation, beaucoup plus complexe, d’appariement flou). La situation typique est l’appariement entre deux sources de données selon un identifiant individuel ou un identifiant de code commune, ce qui est notre cas.
Il est recommandé de lire ce guide assez complet sur la question des jointures avec R qui donne des recommandations également utiles en python
.
On utilise de manière indifférente les termes merge ou join. Le deuxième terme provient de la syntaxe SQL. En pandas
, dans la plupart des cas, on peut utiliser indifféremment df.join
et df.merge
Exercice 7: Calculer l'empreinte carbone par habitant
-
Créer une variable
emissions
qui correspond aux émissions totales d’une commune -
Faire une jointure à gauche entre les données d’émissions et les données de cadrage. Comparer les émissions moyennes des villes sans match (celles dont des variables bien choisies de la table de droite sont NaN) avec celles où on a bien une valeur correspondante dans la base Insee
-
Faire un inner join puis calculer l’empreinte carbone (l’émission rapportée au nombre de ménages fiscaux) dans chaque commune. Sortir un histogramme en niveau puis en log et quelques statistiques descriptives sur le sujet.
-
Regarder la corrélation entre les variables de cadrage et l’empreinte carbone. Certaines variables semblent-elles pouvoir potentiellement influer sur l’empreinte carbone ?
Exercices bonus
Les plus rapides d’entre vous sont invités à aller un peu plus loin en s’entraînant avec des exercices bonus qui proviennent du site de Xavier Dupré. 3 notebooks en lien avec numpy
et pandas
vous y sont proposés :
- Calcul Matriciel, Optimisation : énoncé / corrigé
- DataFrame et Graphes : énoncé / corrigé
- Pandas et itérateurs : énoncé / corrigé