Académique Documents
Professionnel Documents
Culture Documents
1 Le module Pandas
Le module Pandas permet de lire et traiter des blocs de données de manière pratique et facile à
interpreter. Il utilise un type de données qu’on appelle DataFrame. Un DataFrame se représente
comme un tableau. Mais en pratique, il s’agit d’un dictionnaire dont les clés sont les noms des
colonnes formant le tableau. Chaque colonne représente un type de données différent. Il est
également possible de nommer les ligne du tableau.
[1]: import pandas as pd # dans la suite, nous pouvons appeler pandas avec pd
# import matplotlib
# import numpy as np
import datetime as dt
1
[7]: # decouvrir les 3 dernieres lignes
adresses.tail(3)
[9]: # afficher une colonne dont on connait le nom. ATTENTION: les majuscules et␣
,→miniscules ont une importance
adresses['COL_A'][:6]
[9]: 0 JJJJ
1 2095
2 530
3 1813
4 120
5 906
Name: COL_A, dtype: object
[17]: # afficher une liste de colonnes dont on connait le nom. ATTENTION: les␣
,→majuscules et miniscules ont une importance
adresses[['COL_A','COL_B']][:4]
[18]: (945, 3)
2
1.2 Deuxième exemple : “Bien” lire les dates
[6]: # Premier exemple: La date telle qu'on la souhaite est déjà une colonne en soi
data_dates = pd.read_csv('../media/dates_1.csv')
data_dates.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 3 non-null object
1 product 3 non-null object
2 price 3 non-null int64
dtypes: int64(1), object(2)
memory usage: 200.0+ bytes
[7]: data_dates
Commentaires: la date est lue comme un object par pandas mais nous on a le type date. Cor-
rigeons cela en passant les noms des colonnes qui sont des dates dans le paramètre parse_dates
:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 date 3 non-null datetime64[ns]
1 product 3 non-null object
2 price 3 non-null int64
dtypes: datetime64[ns](1), int64(1), object(1)
memory usage: 200.0+ bytes
[9]: data_dates
3
[10]: # mettre la date en index
data_dates = pd.read_csv('../media/dates_1.csv', index_col=0,␣
,→parse_dates=['date'], dayfirst=True)
data_dates
[11]: data_dates.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 3 entries, 2019-01-01 to 1998-03-01
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 product 3 non-null object
1 price 3 non-null int64
dtypes: int64(1), object(1)
memory usage: 72.0+ bytes
data_dates2
4
2019-01-30 10:21:23 B 20
2019-02-01 09:35:01 C 30
2019-02-02 18:20:03 A 10
2019-02-05 17:30:01 B 20
2019-02-06 12:31:03 C 30
data_unicef.head()
2018 29
2019 19
2016 13
2012 12
2015 11
2014 10
2017 10
2013 6
2010 5
2020 5
2011 4
2006 3
2007 3
5
2005 1
Name: Annee, dtype: Int64
[6]: # Nous aimerons connaitre quelles sont les données récoltées en 2018
data_2018 = data_unicef[data_unicef['Annee'] == 2018]
data_2018[:5] # Une autre manière d'afficher les 5 premieres lignes
[8]: # Ajout d'une colonne : difference entre le pourcentage des mariées avant 15␣
,→ans et les mariées avant 18ans
6
1.5 Un peu de nettoyage
[11]: sub_cols = ['Avant_15', 'Avant_18']
# Affecter le type float aux colonnes
for sc in sub_cols:
data_unicef[sc] = pd.to_numeric(data_unicef[sc], errors='coerce')
data_unicef.head()
1.6 A FAIRE
1. Afficher les données récoltées en 2018 et où plus de 5% du nombre total des filles de l’année
ont été mariées avant 18 ans
2. Ajouter une colonne (booléen) qui dit si la ligne contient des données dans la colonne ‘Mar-
ried_15’
1.7 Aggrégation
Dans cette partie, il s’agira d’aggréger les données en groupe et y effectuer des actions.
pandas.groupby : regroupe une dataframe en se basant sur l’unicité des éléments d’une colonne
ou d’une série de colonnes.
Paramètres : + by : la colonne ou le groupe de colonnes utilisé pour le regroupement + axis : 0 si
regroupement sur les valeurs en ligne ou 1 pour les colonnes. Par défaut axis=0 + sort : booleen.
Trie les valeurs des colonnes de regroupement. Par défaut sort=True. + dropna : booleen. Si
“True”, et si les valeurs clés des groupes contient des valeurs NA, les clés NA seront supprimées.
Par défaut dropna=True.
Un intérêt des groupBy est de pouvoir appliquer des fonctions types ou implementées. Des fonctions
types connues sont mean, sum, std, min, max, count, etc.
Avant d’appliquer un groupby + fonction, s’assurer que toutes les fonctions peuvent être appliquées
aux colonnes de la dataframe. Il s’agira de travailler avec une dataframe plus petite au besoin.
Après l’opération groupby, les colonnes de regroupement deviennents les index.
7
data_dep_small =␣
,→data_dep[["Departement","2002_2013_Percentage","1992_2002_Percentage",␣
,→"1979_1992_Percentage"]]
data_dep_agg1 = data_dep_small.groupby(["Departement"]).mean()
data_dep_agg1
1979_1992_Percentage
mean std
Departement
ALIBORI 3.665000 0.717656
ATACORA 2.337778 0.689489
ATLANTIQUE 2.463750 1.336530
8
BORGOU 3.753750 0.827266
COLLINES 3.356667 0.513524
COUFFO 2.701667 0.563717
DONGA 1.580000 1.471847
LITTORAL 3.760000 NaN
MONO 2.226667 0.704008
OUEME 2.266667 0.775919
PLATEAU 2.812000 0.858877
ZOU 2.090000 0.611453
Remarque :
data_dep_agg2 est un multilevel columns dataframe. Donc attention lors de l’utilisation
des colonnes. Par exemple, s’il faut appeler la premiere colonne il faudra utiliser
data_dep_agg2["2002_2013_Percentage"]["mean"]. Il est aussi possible de renommer les
colonnes et de revenir à un seul niveau de colonnes.
[31]: print(data_dep_agg2["2002_2013_Percentage"]["mean"])
Departement
ALIBORI 4.611667
ATACORA 3.017778
ATLANTIQUE 3.827500
BORGOU 4.478750
COLLINES 2.560000
COUFFO 3.101667
DONGA 4.075000
LITTORAL 0.180000
MONO 2.911667
OUEME 3.900000
PLATEAU 3.862000
ZOU 3.150000
Name: mean, dtype: float64
[32]: print(data_dep_agg2.columns)
cols = ['_'.join(v for v in t ) for t in data_dep_agg2.columns]
print(cols)
MultiIndex([('2002_2013_Percentage', 'mean'),
('2002_2013_Percentage', 'std'),
('1992_2002_Percentage', 'mean'),
('1992_2002_Percentage', 'std'),
('1979_1992_Percentage', 'mean'),
('1979_1992_Percentage', 'std')],
)
['2002_2013_Percentage_mean', '2002_2013_Percentage_std',
'1992_2002_Percentage_mean', '1992_2002_Percentage_std',
'1979_1992_Percentage_mean', '1979_1992_Percentage_std']
9
[33]: # enlver le niveau 0 des colonnes
data_dep_agg2.columns = data_dep_agg2.columns.droplevel(level=0)
# affichage
print("Premier affichage après reduction du niveau de colonnes...")
data_dep_agg2
1992_2002_Percentage_mean 1992_2002_Percentage_std \
10
Departement
ALIBORI 3.945000 0.918776
ATACORA 3.246667 1.417119
ATLANTIQUE 2.948750 2.611734
BORGOU 4.432500 0.402306
COLLINES 4.703333 1.117795
COUFFO 2.755000 0.885229
DONGA 3.652500 0.554820
LITTORAL 2.170000 NaN
MONO 2.448333 0.869308
OUEME 2.407778 1.493199
PLATEAU 2.796000 1.891238
ZOU 2.064444 1.071262
1979_1992_Percentage_mean 1979_1992_Percentage_std
Departement
ALIBORI 3.665000 0.717656
ATACORA 2.337778 0.689489
ATLANTIQUE 2.463750 1.336530
BORGOU 3.753750 0.827266
COLLINES 3.356667 0.513524
COUFFO 2.701667 0.563717
DONGA 1.580000 1.471847
LITTORAL 3.760000 NaN
MONO 2.226667 0.704008
OUEME 2.266667 0.775919
PLATEAU 2.812000 0.858877
ZOU 2.090000 0.611453
Lambda
Si l’operation qu’on souhaite faire sur une colonne de la dataframe n’est pas une simple operation
(somme ou multiplication), on peut utiliser le mot clé “lambda” qui permet de specifier sa propre
fonction
[35]: key A B
0 K0 4 8
1 K1 0 6
2 K2 3 7
3 K3 5 6
4 K4 0 3
5 K5 2 5
Supposons qu’on veuille créer une colonne ‘C’ qui est égal à:
11
B/A si A different de 0
B/2 sinon
# Une deuxième manière de faire. Pour changer, nous appelerons 'C' par 'C1'
# Nous allons commencer par créer une fonction qui va prendre en entrée 2␣
,→paramètres
def myLambdaFunc(x):
if x[0]==0:
return x[1]/2
else:
return x[1]/x[0]
df_l['C1'] = df_l[['A', 'B']].apply(myLambdaFunc, axis=1)
df_l
[36]: key A B C C1
0 K0 4 8 2.000000 2.000000
1 K1 0 6 3.000000 3.000000
2 K2 3 7 2.333333 2.333333
3 K3 5 6 1.200000 1.200000
4 K4 0 3 1.500000 1.500000
5 K5 2 5 2.500000 2.500000
Quand on utilise lambda avec plus d’une colonne, il faut absolument avoir le mot clé “axis=1” pour
spécifier qu’on fait les calculs sur les colonnes.
lambda peut être aussi utilisé si la methode pour de calcul lors d’une agregation n’est pas usuelle
(mean, stp, max, min)
1.8 Jointure
Join
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False) :
permet de joindre 2 dataFrame soit en utilisant l’index ou soit en précisant une colonne.
Paramètres :
• other : Correspond au second dataFrame
• on : Permet de préciser sur quelles colonnes il faut faire la jointure. Par défaut, on=None et
alors la jointure se fera sur les index.
• how : Permet de préciser comment gérer la jointure.
– Si ‘left’ (valeur par défaut), la jointure se fera en utilisant l’index ou la colonne spécifiée
de la dataframe appelant
– Si ‘right’, la jointure se fera en utilisant l’index ou la colonne spécifiée de la dataframe
other
12
– Si ‘outer’, le résulat final sera une union des valeurs de la colonne (ou index) spécifiée
pour la jointure.
– Si ‘inner’, le résulat final sera une intersection des valeurs de la colonne (ou index)
spécifiée en préservant l’ordre des valeurs de la dataframe appelante.
• lsuffix : Permet de rajouter le suffixe spécifié si les 2 dataframes possèdent des colonnes
de mêmes nom autre que les colonnes sur lesquelles se font la jointure. Le suffixe précisé par
lsuffix sera uniquement appliqué sur la dataframe appelante. Par défaut, aucun suffixe ne
sera appliqué sur la dataframe de gauche.
• rsuffix : Permet de rajouter le suffixe spécifié si les 2 dataframes possèdent des colonnes
de mêmes nom autre que les colonnes sur lesquelles se font la jointure. Le suffixe précisé par
rsuffix sera uniquement appliqué sur la dataframe other. Par défaut, aucun suffixe ne sera
appliqué sur la dataframe de droite.
Merge
DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None,
left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'),
copy=True, indicator=False, validate=None) : Permet de fusionner deux dataframes,
dans le même style de la jointure. On retrouve des paramètres similaires à ceux de la jointure
[37]: key A
0 K0 A0
1 K1 A1
2 K2 A2
3 K3 A3
4 K4 A4
5 K5 A5
[38]: key B
0 K0 B0
1 K1 B1
2 K2 B2
13
df3 = df1.join(df2, lsuffix='_appelant', rsuffix='_appele')
df3
[42]: key A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
[43]: key A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
3 K3 A3 NaN
4 K4 A4 NaN
5 K5 A5 NaN
Il existe beaucoup de possibilités avec la librairie Pandas. N’hésitez pas à faire des recherches si
vous voulez utiliser une fonction qui n’a pas encore été abordée dans ce chapitre.
1.9 Exercice:
Le fichier bibliotheques contient les statistiques d’entrée dans les bibliothèques du réseau Fondation
Vallet - CAEB - BE.
1. Importer ces données dans une dataframe
2. Combien de bibliothèques dispose ce réseau ? Listez les.
3. Trouver la bibliothèque qui a le plus fort taux de participation.
4. Tracer l’histogramme du nombre de participations pour les étudiants par ville.
5. Quelle bibliothèque a acueillli le plus d’élèves du primaire en May 2019 ?
14