Files
training.python.datascience/documentation/01-c-pandas-actions.md
2025-07-04 19:58:11 +02:00

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() ou isnull() : ces deux méthodes retournent un masque booléen indiquant les entrées manquantes.
  • notna() ou notnull() : ces méthodes fonctionnent comme les précédentes, mais renvoient True 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 colonnes
  • df.sum() : Calcule la somme des colonnes
  • df.std() : Calcule l'écart-type (racine de la variance)
  • df.var() : Calcule la variance
  • df.median() : Valeur centrale des éléments d'une série
  • df.quantile(q) : Calcule un quantile (q entre 0.0 et 1.0)
  • df.mode() : Renvoie un DataFrame des valeurs modales de chaque colonne
  • df.max() et df.min() : Calculer les extrêmes
  • df.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")