28 KiB
title, author
title | author |
---|---|
Manipuler des données avec Pandas | Steve Kossouho |
Analyse de données fichier avec Pandas
Les Index
dans une Series
Un objet de type Series
est un jeu de données à une dimension. Ce qui n'empêche pas d'associer
un index à chacune des lignes du document. Un des intérêts est de pouvoir associer une étiquette
à chacune des données, par exemple un moment dans le temps. Cela permet d'obtenir une série temporelle
en bonne et dûe forme.
import pandas as pd
s0 = pd.Series(data=[2, 5, 2, 6], index=["ligne1", "ligne2", "ligne3", "ligne4"])
s1 = pd.Series(data=[2, 5, 2, 6], index=pd.date_range("2023-01-01", "2023-01-31", 4))
s2 = pd.Series(data=[2, 5, 2, 6], index=["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"])
s3 = pd.Series(data=[2, 5, 2, 6]) # Créer une série sans index
s3 = s3.set_axis(["ligne1", "ligne2", "ligne3", "ligne4"]) # Utilise ces valeurs comme index. Renvoie une nouvelle série.
print(s1, s2)
print(s0, s3)
Petit aparté : utilisation de date_range()
La fonction de Pandas nommée date_range()
permet de générer une suite de dates, qu'on pourrait
utiliser pour générer des colonnes d'un DataFrame
ou des index à associer aux lignes d'un DataFrame
ou une Series
.
La fonction permet de générer des dates à intervalles réguliers, mais peut faire beaucoup plus intéressant :
import pandas as pd
# Génère une liste de 8 dates, contenant la date de début et de fin, ainsi que 6 autres dates
# uniformément dispersés (avec les heures, minutes, secondes et **nanosecondes**)
print(pd.date_range("2023-01-01", "2023-01-31", periods=8)
Un problème potentiel de cette méthode, c'est justement qu'on n'obtient pas toujours des dates exactes à minuit. Cela peut s'arranger, en utilisant la fonction avec un autre argument.
TODO: Reformuler ce truc
Si on utilise la même fonction, mais en utilisant l'argument freq
au lieu de l'argument periods
(on ne peut
pas utiliser les deux en même temps), on peut demander à Pandas de générer une suite de dates, répondant à certains critères, documentés
ici
import pandas as pd
# Génère une liste de dates, contenant la date de début et de fin, une par jour du calendrier
print(pd.date_range("2023-01-01", "2023-01-31", freq="D")) # D signifie chaque jour de la semaine
print(pd.date_range("2023-01-01", "2023-01-31", freq="W-SUN")) # W-SUN signifie chaque dimanche
print(pd.date_range("2023-01-01", "2023-01-31", freq="W-MON")) # W-MON signifie chaque lundi
print(pd.date_range("2023-01-01", "2023-01-31", freq="W-TUE")) # W-MON signifie chaque mardi
print(pd.date_range("2023-01-01", "2023-01-02", freq="H")) # H signifie chaque heure
Les données absentes (Not a Number
)
Dans un objet Series
ou un objet DataFrame
, toutes les cellules n'ont pas forcément de données.
Prenons un exemple au hasard : une table contenant des informations d'identité, et qui contient des colonnes telles que nom
, prenom
, et nom de naissance
, peut présenter des lignes de contenu où la colonne nom de naissance
ne sera pas renseignée.
Lorsque c'est le cas, Pandas représente le contenu de la cellule comme étant NaN
(not a number), une donnée qui en Python standard serait la valeur None
{.python}.
Dans de nombreux calculs fournis par Pandas, il est souvent facile d'exclure les cellules NaN
des
résultats, voire de retirer des informations selon l'état de remplissage de cellules.
Gestion des données manquantes (NaN)
Pandas offre plusieurs méthodes pour gérer les données manquantes, identifiées par la valeur NaN
(Not a Number) :
isna()
ouisnull()
: ces deux méthodes retournent un masque booléen indiquant les entrées manquantes.notna()
ounotnull()
: ces méthodes fonctionnent comme les précédentes, mais renvoientTrue
pour les entrées non manquantes.dropna()
: cette méthode permet de supprimer les lignes (ou colonnes, selon l'axe choisi) contenant des entrées manquantes.fillna()
: cette méthode permet de remplir les entrées manquantes avec une valeur spécifiée.
Exemple d'utilisation :
import pandas as pd
import numpy as np
# Création d'un DataFrame avec des valeurs manquantes
df = pd.DataFrame({
"A": [1, 2, np.nan],
"B": [5, np.nan, np.nan],
"C": [1, 2, 3]
})
print(df)
# Utilisation de dropna() pour supprimer les lignes avec des valeurs NaN
df_drop = df.dropna()
# On peut aussi choisir quelles colonnes considérer pour la vérification des valeurs NaN
# Supprimer les lignes entières où on a NaN dans la colonne "A" uniquement
df_drop2 = df.dropna(subset=["A"])
print(df_drop)
print(df_drop2)
Pour remplacer des valeurs NaN
dans un DataFrame
, on a plusieurs possibilités :
# Utilisation de fillna() pour remplir les valeurs manquantes
# Ici, on remplace TOUTES les valeurs NaN du DataFrame par une valeur choisie
df_fill = df.fillna(value='FILL VALUE')
# Si on souhaite choisir la valeur par défaut par colonne
# Ici, on indique qu'il faut remplacer les valeurs NaN de la colonne "A"
# par 0, et les valeurs NaN de la colonne "B" par -1
df_fill2 = df.fillna(value={"A": 0, "B": -1})
print(df_fill)
print(df_fill2)
Pour avoir une carte des valeurs NaN
ou équivalentes dans un DataFrame
, on a les méthodes isna()
:
# Utilisation de isna() pour récupérer un DataFrame de valeurs booléennes.
# On aura un `True` pour les valeurs `None`, `NaN`, `NaT` etc.
df_empty_map = df.isna()
print(df_empty_map)
Gestion des index
Nous avons déjà vu comment utiliser des index avec un DataFrame
. Il existe plusieurs méthodes utiles pour gérer ces index :
reset_index()
: Permet de réinitialiser l'index à un index par défaut (0, 1, 2, ...).set_index()
: Utiliser une colonne différente pour l'index.
Exemple d'utilisation :
import pandas as pd
# Création d'un DataFrame avec un index
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}, index=["x", "y", "z"])
print(df)
# Réinitialisation de l'index
df = ...
# df.reset_index() renvoie un nouveau DataFrame avec l'index mis à jour.
df_reset = df.reset_index()
# df.reset_index(inplace=True) modifie le DataFrame en modifiant son index.
df.reset_index(inplace=True)
print(df_reset)
# Utilisation d'une autre colonne pour l'index
# Les valeurs de la colonne "A" seront utilisées comme index pour référencer les lignes
df_set = df.set_index("A")
print(df_set)
Filtrage et modifications d'un dataframe
Pandas offre une multitude de méthodes pour filtrer et modifier un DataFrame
. Par exemple, il est possible de sélectionner des colonnes ou des lignes spécifiques, de filtrer selon certaines conditions, ou encore de modifier des valeurs.
Exemple d'utilisation :
import pandas as pd
# Création d'un DataFrame
df = pd.DataFrame({"A": [1, 2, 3, 4], "B": [5, 6, 7, 8], "C": ["a", "b", "c", "d"]})
# Sélection d'une colonne
print(df["A"])
# Sélection de plusieurs colonnes
print(df[["A", "B"]])
# Filtrage selon une condition
# On peut filtrer avec des conditions sans passer par df.iloc
# Mais ce sera plus explicite d'utiliser df.iloc
print(df.loc[df["A"] > 2]) # Récupérer les lignes où A > 2
print(df.loc[(df["A"] > 2) & (df["B"] == 8)]) # Récupérer les lignes où A > 2 et B = 8
print(df.loc[~(df["A"] > 2) & (df["B"] == 8)]) # Récupérer les lignes où A n'est pas > 2 et B = 8
# Modification de valeurs :
# Changer les lignes de df où la colonne "A" contient une
# valeur supérieure à 2, et y mettre la valeur 10 dans les colonnes B et C
df.loc[df["A"] > 2, ["B", "C"]] = 10
# Si je veux mettre deux valeurs différentes dans B et C lorsque la condition
# est vérifiée, j'écrirai plutôt
df.loc[df["A"] > 2, ["B", "C"]] = (9, 12)
print(df)
Tri des lignes d'un DataFrame
Il est fréquent de vouloir réorganiser les données d'un DataFrame
via un tri sur une ou plusieurs colonnes.
Le type propose naturellement une méthode nommée .sort_values()
Slicing et lignes de DataFrame
Nous avons vu qu'il est possible de filtrer un DataFrame
via des critères avancés. De façon plus générale, le filtrage de lignes peut se faire avec deux attributs :
df.iloc
: extraire des lignes individuelles par leur numéro séquentiel dans le dataframe;df.loc
: extraire des lignes individuelles par la valeur assignée comme index aux lignes du document.
Les deux méthodes s'utilisent généralement de la même manière, en faisant attention à utiliser des alias d'index dans le
cas de df.loc
.
Extraire une ligne d'un DataFrame
Au même titre que dans une liste Python, il est très simple d'extraire une ligne d'un objet DataFrame
:
import pandas as pd
df = pd.DataFrame({"A": [1, 2, 3, 4], "B": [5, 6, 7, 8], "C": ["a", "b", "c", "d"]}, index=["l1", "l2", "l3", "l4"])
row_a = df.loc["l1"] # extraire la première ligne
row_b = df.iloc[0] # extraire la première ligne
print(row_a, row_b)
Extraire plusieurs lignes distinctes d'un DataFrame
Impossible avec des types standard en Python, il est très simple avec Pandas d'extraire des lignes distinctes d'un objet DataFrame
:
import pandas as pd
df = pd.DataFrame({"A": [1, 2, 3, 4], "B": [5, 6, 7, 8], "C": ["a", "b", "c", "d"]}, index=["l1", "l2", "l3", "l4"])
rows_a = df.iloc[[0, 2]] # extraire les 1e et 3e lignes
print(rows_a)
Filtrer les lignes d'un DataFrame
avec des booléens
On peut filtrer les lignes d'un objet DataFrame
en passant une liste de booléens. Pour chaque booléen valant True
, la ligne
correspondante sera conservée dans la sortie :
import pandas as pd
df = pd.DataFrame({"A": [1, 2, 3, 4], "B": [5, 6, 7, 8], "C": ["a", "b", "c", "d"]}, index=["l1", "l2", "l3", "l4"])
rows_a = df.iloc[[False, True, True, False]] # extraire les 2e et 3e lignes
print(rows_a)
Cette possibilité de filtrer via une liste de booléens, associée au fonctionnement des opérateurs sur les Series
,
permet des choses très intéressantes pour facilement filtrer des DataFrame
Filtrer avec des conditions
Utiliser des opérateurs de comparaison sur une colonne de données renverra toujours une série de même longueur, contenant des booléens indiquant si la comparaison était vraie pour chaque valeur.
import pandas as pd
df = pd.DataFrame({
"A": [1, -2, 3, -4],
"B": [5, 6, 7, 8],
"C": ["ant", "ball", "chord", "double"]
}, index=["l1", "l2", "l3", "l4"])
# Masque de valeurs positives
positive_a = df["A"] >= 0
# L'opposé d'une condition utilise l'opérateur
# de complément binaire, le ~
exclude_cond = ~df["A"] == 0
# Masque de valeurs dans une plage
range_a = df["A"].between(0, 100, inclusive="both")
Les séries de booléens résultantes peuvent naturellement assemblées entre elles via des opérations logiques, booléennes :
import pandas as pd
df = pd.DataFrame({"A": [1, -2, 3, -4], "B": [5, 6, 7, 8], "C": ["ant", "ball", "chord", "double"]}, index=["l1", "l2", "l3", "l4"])
multi_condition = (df["A"] >= 0) & (df["B"] > 6) # lignes où A est positif et B est > 6
print(multi_condition)
Conditions sur des chaînes de caractères
Il est facile d'utiliser des opérateurs classiques pour tester des conditions sur des
colonnes d'un objet DataFrame
. Par exemple :
filtered_df = df[df["column"] > 1]
Si l'on souhaite filtrer sur une colonne textuelle, on peut être intéressé
de pouvoir considérer une partie d'une chaîne, ou bien ignorer la casse du texte.
Pour cela nous avons sur les objets Series
un attribut .str
:
filtered_df = df[df["column"].str.contains("(?i)texte")]
La méthode comprend les expressions régulières pour plus de contrôle sur les valeurs à tester.
Conditions avec des fonctions
Il peut arriver qu'une condition de test à appliquer à une colonne nécessite autre chose que simplement le contenu
brut de la colonne; par exemple, le nombre de caractères d'une colonne textuelle pourrait être utilisé pour
discriminer les résultats. Dans ce cas de figure, on utilisera plutôt la méthode apply
de la série :
import pandas as pd
df = pd.DataFrame(
{"A": [1, -2, 3, -4], "B": [5, 6, 7, 8], "C": ["ant", "ball", "chord", "double"]},
index=["l1", "l2", "l3", "l4"]
)
# Dire si une ligne de C a plus de 4 caractères
# La fonction renvoie une série de valeurs booléennes
long_c = df["C"].apply(lambda val: len(val) > 4)
print(long_c)
print(df.loc[long_c])
Slicing sur les lignes
La syntaxe normale du slicing fonctionne sur les lignes d'un DataFrame
, ce qui vous permet de récupérer simplement
une partition des lignes du DataFrame
original.
import pandas as pd
df = pd.DataFrame(
{"A": [1, -2, 3, -4], "B": [5, 6, 7, 8], "C": ["ant", "ball", "chord", "double"]},
index=["l1", "l2", "l3", "l4"]
)
partition = df.iloc[0:2]
print(partition)
Plus : Multiple slicing sur les lignes
La syntaxe normale du slicing fonctionne sur les lignes d'un DataFrame
, ce qui vous permet de récupérer simplement
une partition des lignes du DataFrame
original. Un outil de numpy
nous permet d'appliquer un slicing multiple sur les
lignes d'un DataFrame
:
import pandas as pd
import numpy as np
df = pd.DataFrame(
{"A": [1, -2, 3, -4], "B": [5, 6, 7, 8], "C": ["ant", "ball", "chord", "double"]},
index=["l1", "l2", "l3", "l4"]
)
partition = df.iloc[np.r_[0:1, 2:4]] # extraire les lignes 0 et 2 à 3 avec du slice
print(partition)
Grouper les contenus d'un DataFrame pour calculs
Pandas propose des méthodes pour grouper les données selon certains critères et effectuer des calculs sur ces groupes.
C'est ce qu'on appelle souvent l'opération de group by
(groupement).
Cela est particulièrement utile pour l'analyse de données.
Exemple d'utilisation :
import pandas as pd
import numpy as np
# Création d'un DataFrame
df = pd.DataFrame({
"A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
"B": ["one", "one", "two", "three", "two", "two", "one", "three"],
"C": np.random.randn(8),
"D": np.random.randn(8)
})
# Grouper par colonne "A" et calculer la somme sur chaque groupe
grouped = df.groupby("A").sum()
print(grouped)
Fusion de dataframes
Pandas propose plusieurs méthodes pour combiner des DataFrame
, comme concat()
, merge()
, ou join()
. Ces opérations sont similaires à celles que l'on peut réaliser avec des bases de données SQL.
Exemple d'utilisation :
import pandas as pd
# Création de deux DataFrame
df1 = pd.DataFrame({
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"]
})
df2 = pd.DataFrame({
"A": ["A4", "A5", "A6", "A7"],
"B": ["B4", "B5", "B6", "B7"],
"C": ["C4", "C5", "C6", "C7"],
"D": ["D4", "D5", "D6", "D7"]
})
# Concaténation des deux DataFrame
result = pd.concat([df1, df2])
print(result)
Manipulation des formats de dates
Pandas offre une multitude de méthodes pour manipuler les dates. Vous pouvez convertir des chaînes de caractères en dates, extraire des composants spécifiques d'une date (comme l'année, le mois, le jour, etc.), ou encore effectuer des calculs avec des dates.
Exemple d'utilisation :
import pandas as pd
# Création d'un DataFrame avec une colonne date
df = pd.DataFrame({
"date": ["2023-01-01", "2023-01-02", "2023-01-03"],
"value": [1, 2, 3]
})
# Afficher les types des colonnes pour s'assurer que la colonne de date a le bon type
print(df.dtypes) # Regardez le résultat pour être sûr
# Si le type est incorrect, faire la conversion de la colonne vers le type datetime
df["date"] = pd.to_datetime(df["date"])
# Extraction de l'année, du mois, et du jour dans 3 nouvelles colonnes
df["year"] = df["date"].dt.year
df["month"] = df["date"].dt.month
df["day"] = df["date"].dt.day
print(df)
Mesures statistiques variées sur les DataFrames
Pandas propose plusieurs méthodes pour calculer des statistiques sur un DataFrame
, comme la moyenne (mean()
), la somme (sum()
), l'écart-type (std()
), le minimum (min()
), le maximum (max()
), et bien d'autres.
Exemple d'utilisation :
import pandas as pd
# Création d'un DataFrame
df = pd.DataFrame({
"A": [1, 2, 3, 4, 5],
"B": [6, 7, 8, 9, 10]
})
# Calcul de la moyenne, de la somme, et de l'écart-type sur chaque colonne
mean = df.mean() # Ceci est une `Series` avec une valeur calculée par colonne
sum = df.sum() # Ceci aussi est une `Series`
std = df.std() # Pareil
print(mean)
print(sum)
print(std)
Comment ajouter une Series
comme nouvelle ligne d'un DataFrame
Cela peut être intéressant d'ajouter à un DataFrame
une ligne qui provient d'un objet Series
(par exemple, les résultats de moyennes, sommes ou écarts-types etc.) Pour cela, c'est assez simple, il faut se servir de l'attribut .loc
d'un DataFrame
:
import pandas as pd
# Création d'un DataFrame
df = pd.DataFrame({"A": [1, 2, 3, 4, 5], "B": [6, 7, 8, 9, 10]})
# Calcul de la moyenne, de la somme, et de l'écart-type sur chaque colonne
mean = df.mean() # Ceci est une `Series` avec une valeur calculée par colonne
# Ajouter la `Series` dans `mean` comme nouvelle ligne dans `df` dont l'index est "moyenne"
df.loc["moyenne"] = mean
df.loc["hasard"] = [99, 25] # On peut même définir des lignes avec des valeurs dans une liste
print(df) # Une nouvelle ligne "moyenne" devrait être présente dans le DataFrame
Noms des méthodes les plus fréquemment utilisées
Pour faire des calculs statistiques sur les colonnes d'un DataFrame
, les méthodes disponibles de
base dans Pandas ont des noms pas toujours faciles à deviner :
df.mean()
: Calcule la moyenne des colonnesdf.sum()
: Calcule la somme des colonnesdf.std()
: Calcule l'écart-type (racine de la variance)df.var()
: Calcule la variancedf.median()
: Valeur centrale des éléments d'une sériedf.quantile(q)
: Calcule un quantile (q entre 0.0 et 1.0)df.mode()
: Renvoie un DataFrame des valeurs modales de chaque colonnedf.max()
etdf.min()
: Calculer les extrêmesdf.cum*()
: Fonctions cumulatives qui renvoient des DataFrame
Mode d'un DataFrame
Le mode d'un DataFrame
renvoie un DataFrame
avec toutes les colonnes, et autant de lignes qu'il y a de valeurs modales par colonne. (Une valeur modale est la valeur qui revient le plus souvent dans une série)
Si j'ai un DataFrame
avec une colonne A
et une colonne B
, et que A
possède une seule valeur modale qui est 10
, et que B
possède 3 valeurs modales qui sont "pomme"
, "citron"
, et "ananas"
, le résultat du mode du DataFrame
ressemblera à ça :
A B
10 pomme
NaN citron
NaN ananas
Les colonnes où il y a moins de valeurs modales sont remplies avec des NaN
.
Faire des liaisons entre plusieurs DataFrame
Des fois, on est obligé de récupérer des informations différentes depuis plusieurs DataFrame
qui ont des données en commun. Par exemple :
- Une table d'assurés sociaux :
numero_secu
,prenom
,nom
,naissance
... - Une table de remboursements médicaments :
num_secu
,montant
,date
,categorie
...
Si on veut travailler sur le DataFrame
des remboursements, en y ajoutant les informations de prénom, nom et date de naissance pour chaque remboursement, on peut faire une fusion avec Pandas.
import pandas as pd
# Imaginez que ces deux fichiers factices correspondent à nos deux Dataframes
df_assures = pd.read_csv("assures.csv")
df_remboursements = pd.read_csv("remboursements.csv")
# On veut partir du DataFrame des remboursements pour y ajouter
# des colonnes prises depuis la liste des assurés.
resultat = df_remboursements.merge(df_assures, how="left", on_left="num_secu", on_right="numero_secu")
print(resultat)
Le résultat qui est affiché contient toutes les colonnes des assurés et des remboursements, et contient autant de lignes que dans la table de "gauche", à savoir df_remboursements
.
Les colonnes sont numero_secu
, prenom
, nom
, naissance
, num_secu
, montant
, date
, categorie
.
Les colonnes num_secu
et numero_secu
auront les memes valeurs, car c'est justement sur ces colonnes qu'on a fait la fusion. Attention cependant !
Stratégie de fusion de DataFrame
La méthode .merge()
accepte un argument how=
qui permet de préciser comment le résultat de la fusion doit etre généré. Les valeurs possibles de cet argument sont : "left"
, "right"
, "inner"
, "outer"
.
Si je possède les DataFrame
suivants :
Personnes
id prenom nom naissance
0 1 Jacques Dupont 1959
1 2 Paul Biya 1947
2 3 Marie Curie 1861
3 5 Jules César 0
Transactions
id_transaction id_client montant
0 1 1 100
1 2 1 500
2 3 2 -90
3 4 2 200
4 5 1 30
5 6 3 15
6 7 2 -60
7 8 1 -10
8 9 1 250
9 10 2 170
10 11 3 90
15 16 4 77
Stratégie left
Si j'utilise la stratégie "left"
, alors toutes les lignes du DataFrame
de gauche (df_remboursements
) seront conservées, et on y ajoutera les colonnes du DataFrame
de droite, en y choisissant comme données celles de la ligne
où la colonne "numero_secu"
a la meme valeur que dans la colonne "num_secu"
.
Si il n'existe pas de ligne dans le DataFrame
de droite où la colonne "numero_secu"
a une valeur qui correspond, les
colonnes ajoutées contiendront NaN
. En gros : on conservera tous les enregistrements de gauche, en ajoutant des NaN
à droite s'il n'y a aucune correspondance trouvée.
Résultat :
id_transaction id_client montant id prenom nom naissance
0 1 1 100 1.0 Jacques Dupont 1959.0
1 2 1 500 1.0 Jacques Dupont 1959.0
2 3 2 -90 2.0 Paul Biya 1947.0
3 4 2 200 2.0 Paul Biya 1947.0
4 5 1 30 1.0 Jacques Dupont 1959.0
5 6 3 15 3.0 Marie Curie 1861.0
6 7 2 -60 2.0 Paul Biya 1947.0
7 8 1 -10 1.0 Jacques Dupont 1959.0
8 9 1 250 1.0 Jacques Dupont 1959.0
9 10 2 170 2.0 Paul Biya 1947.0
10 16 4 77 NaN NaN NaN NaN
Stratégie right
Si j'utilise la stratégie "right"
, alors toutes les lignes du DataFrame
de droite (df_assures
)
seront conservées, et on y ajoutera les colonnes du DataFrame
de gauche, en y choisissant comme données celles de la ligne
où la colonne "num_secu"
a la meme valeur que dans la colonne "num_secu"
. Si plusieurs lignes correspondent, on ajoutera autant de lignes que nécessaire.
Si il n'existe pas de ligne dans le DataFrame
de gauche où la colonne "num_secu"
a une valeur qui correspond, les colonnes ajoutées contiendront NaN
.
Résultat :
id_transaction id_client montant id prenom nom naissance
0 1.0 1.0 100.0 1 Jacques Dupont 1959
1 2.0 1.0 500.0 1 Jacques Dupont 1959
2 5.0 1.0 30.0 1 Jacques Dupont 1959
3 8.0 1.0 -10.0 1 Jacques Dupont 1959
4 9.0 1.0 250.0 1 Jacques Dupont 1959
5 3.0 2.0 -90.0 2 Paul Biya 1947
6 4.0 2.0 200.0 2 Paul Biya 1947
7 7.0 2.0 -60.0 2 Paul Biya 1947
8 10.0 2.0 170.0 2 Paul Biya 1947
9 6.0 3.0 15.0 3 Marie Curie 1861
10 NaN NaN NaN 5 Jules César 0
Stratégie inner
Avec la stratégie inner
on ne garde que les lignes où les colonnes utilisées pour faire la fusion ont une correspondance
de l'autre coté de de la fusion. En gros, on n'ajoute jamais dans le résultat de ligne ou on aurait des colonnes avec NaN
.
Résultat :
id_transaction id_client montant id prenom nom naissance
0 1 1 100 1 Jacques Dupont 1959
1 2 1 500 1 Jacques Dupont 1959
2 5 1 30 1 Jacques Dupont 1959
3 8 1 -10 1 Jacques Dupont 1959
4 9 1 250 1 Jacques Dupont 1959
5 3 2 -90 2 Paul Biya 1947
6 4 2 200 2 Paul Biya 1947
7 7 2 -60 2 Paul Biya 1947
8 10 2 170 2 Paul Biya 1947
9 6 3 15 3 Marie Curie 1861
Stratégie outer
Avec la stratégie outer
on garde toutes lignes et si les colonnes utilisées pour faire la fusion n'ont pas de correspondance
de l'autre coté de la fusion, on ajoute simplement des colonnes avec NaN
..
Résultat :
id_transaction id_client montant id prenom nom naissance
0 1.0 1.0 100.0 1.0 Jacques Dupont 1959.0
1 2.0 1.0 500.0 1.0 Jacques Dupont 1959.0
2 5.0 1.0 30.0 1.0 Jacques Dupont 1959.0
3 8.0 1.0 -10.0 1.0 Jacques Dupont 1959.0
4 9.0 1.0 250.0 1.0 Jacques Dupont 1959.0
5 3.0 2.0 -90.0 2.0 Paul Biya 1947.0
6 4.0 2.0 200.0 2.0 Paul Biya 1947.0
7 7.0 2.0 -60.0 2.0 Paul Biya 1947.0
8 10.0 2.0 170.0 2.0 Paul Biya 1947.0
9 6.0 3.0 15.0 3.0 Marie Curie 1861.0
10 16.0 4.0 77.0 NaN NaN NaN NaN
11 NaN NaN NaN 5.0 Jules César 0.0
Appliquer un Pivot
La méthode pivot
des DataFrame
permet de récupérer une représentation d'un DataFrame
, réorganisé autour de certaines colonnes/index.
Par exemple, si nous avons les données suivantes :
import pandas as pd
df = pd.DataFrame({
'country': ['fra', 'fra', 'fra', 'fra', 'bel', 'bel', 'bel', "bel"],
'district': ['north', 'east', 'west', 'south', 'north', 'east', 'west', 'south'],
'population': [10_000, 30_000, 50_000, 70_000, 20_000, 40_000, 60_000, 80_000],
'extra': ['h', 'i', 'j', 'k', 'l', 'm', 'n', 'o']
})
Si nous appliquons le pivot suivant sur ces données :
df2 = df.pivot(index='district', columns='country', values='population')
Nous obtiendrons les données suivantes :
country bel fra
district
east 40000 30000
north 20000 10000
south 80000 70000
west 60000 50000
L'argument values
est facultatif. S'il est omis, alors le DataFrame
résultant
contiendra des colonnes de type MultiIndex
, un index dont les entrées sont composées de tuples
.
Ici, au lieu d'avoir deux colonnes de pays pour la colonne population
, nous aurons deux colonnes de pays pour la colonne population
, deux colonnes de pays pour la colonne extra
, et ainsi de suite pour toutes les colonnes non utilisées en tant qu'index ou colonnes.
Les noms de ces colonnes seront :
("population", "bel")
("population", "fra")
("extra", "bel")
("extra", "fra")