Accéder au contenu principal

Joining DataFrame in pandas Tutoriel

Dans ce tutoriel, vous apprendrez différentes façons de fusionner plusieurs DataFrame en Python à l'aide de la bibliothèque Pandas.
Actualisé 14 nov. 2024  · 19 min de lecture

Avez-vous déjà essayé de résoudre un défi Kaggle ? Si oui, vous avez peut-être remarqué que dans la plupart des défis, les données qui vous sont fournies sont présentes dans plusieurs fichiers, certaines colonnes étant présentes dans plus d'un fichier. Quelle est la première chose qui vous vient à l'esprit ? Rejoignez-les bien sûr !

Dans ce tutoriel, vous pratiquerez quelques techniques standard de jointure pandas. Plus précisément, vous apprendrez à :

  • Concaténer les DataFrame le long de la ligne et de la colonne.
  • Fusionnez les DataFrame sur des clés spécifiques par différentes logiques de jointure comme la jointure gauche, la jointure interne, etc.
  • Joint les DataFrame par l'index.
  • Fusion conviviale de séries temporelles dans pandas

En cours de route, vous apprendrez également quelques astuces dont vous aurez besoin avant et après l'adhésion.

Adhésion des pandas

Joindre et fusionner des DataFrame est le processus de base pour commencer les tâches d'analyse de données et d'apprentissage automatique. C'est l'une des boîtes à outils que tout analyste ou scientifique des données devrait maîtriser car, dans presque tous les cas, les données proviennent de sources et de fichiers multiples. Il se peut que vous deviez rassembler toutes les données en un seul endroit par une sorte de logique de jointure, puis commencer votre analyse. Les personnes qui travaillent avec des langages de requête de type SQL connaissent sans doute l'importance de cette tâche. Même si vous souhaitez construire quelques modèles d'apprentissage automatique sur certaines données, il se peut que vous deviez fusionner plusieurs fichiers csv dans un seul DataFrame.

Heureusement, vous pouvez compter sur la bibliothèque la plus populaire de Python, Pandas, pour vous venir en aide ! Pandas offre diverses possibilités pour combiner facilement des objets Series, DataFrame et Panel avec divers types de logique d'ensemble pour les index et des fonctionnalités d'algèbre relationnelle dans le cas d'opérations de type join / merge.

Exécutez et modifiez le code de ce tutoriel en ligne

Exécuter le code

pandas Concatenate

Commencez par importer la bibliothèque que vous utiliserez tout au long du tutoriel : pandas

import pandas as pd

Vous effectuerez toutes les opérations de ce tutoriel sur les DataFrame fictifs que vous allez créer. Pour créer un DataFrame, vous pouvez utiliser un dictionnaire Python comme :

dummy_data1 = {
        'id': ['1', '2', '3', '4', '5'],
        'Feature1': ['A', 'C', 'E', 'G', 'I'],
        'Feature2': ['B', 'D', 'F', 'H', 'J']}

Ici, les clés du dictionnaire dummy_data1 sont les noms des colonnes et les valeurs de la liste sont les données correspondant à chaque observation ou ligne. Pour transformer ceci en DataFrame pandas, vous utiliserez la fonction DataFrame() de pandas, ainsi que son argument columns pour nommer vos colonnes :

df1 = pd.DataFrame(dummy_data1, columns = ['id', 'Feature1', 'Feature2'])

df1
  id Fonctionnalité1 Fonctionnalité2
0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J

Comme vous pouvez le constater, vous disposez à présent d'un DataFrame comportant trois colonnes : id, Feature1 et Feature2. Il y a une colonne supplémentaire sans nom que pandas crée intrinsèquement en tant qu'étiquettes de ligne. Comme pour le DataFrame df1 précédent, vous allez créer deux autres DataFrames df2 et df3 :

dummy_data2 = {
        'id': ['1', '2', '6', '7', '8'],
        'Feature1': ['K', 'M', 'O', 'Q', 'S'],
        'Feature2': ['L', 'N', 'P', 'R', 'T']}
df2 = pd.DataFrame(dummy_data2, columns = ['id', 'Feature1', 'Feature2'])

df2
  id Fonctionnalité1 Fonctionnalité2
0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T
dummy_data3 = {
        'id': ['1', '2', '3', '4', '5', '7', '8', '9', '10', '11'],
        'Feature3': [12, 13, 14, 15, 16, 17, 15, 12, 13, 23]}
df3 = pd.DataFrame(dummy_data3, columns = ['id', 'Feature3'])

df3
  id Fonctionnalité3
0 1 12
1 2 13
2 3 14
3 4 15
4 5 16
5 7 17
6 8 15
7 9 12
8 10 13
9 11 23

 concat()

Pour concaténer simplement les DataFrame le long de la ligne, vous pouvez utiliser la fonction concat() de pandas. Vous devrez transmettre les noms des DataFrame dans une liste comme argument à la fonction concat() :

df_row = pd.concat([df1, df2])

df_row
  id Fonctionnalité1 Fonctionnalité2
0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J
0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T

Vous pouvez remarquer que les deux DataFrame df1 et df2 sont maintenant concaténés en un seul DataFrame df_row le long de la ligne. Cependant, les étiquettes des lignes semblent être erronées. Si vous souhaitez que les étiquettes de ligne s'ajustent automatiquement en fonction de la jointure, vous devez définir l'argument ignore_index sur True lors de l'appel de la fonction concat() :

df_row_reindex = pd.concat([df1, df2], ignore_index=True)

df_row_reindex
  id Fonctionnalité1 Fonctionnalité2
0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J
5 1 K L
6 2 M N
7 6 O P
8 7 Q R
9 8 S T

Les étiquettes des lignes sont maintenant correctes !

pandas vous offre également la possibilité d'étiqueter les DataFrames, après la concaténation, avec une clé afin que vous puissiez savoir quelles données proviennent de quel DataFrame. Vous pouvez obtenir le même résultat en passant des clés d'argument supplémentaires spécifiant les noms des étiquettes des DataFrames dans une liste. Ici, vous effectuerez la même concaténation avec les clés x et y pour les DataFrame df1 et df2 respectivement.

frames = [df1,df2]
df_keys = pd.concat(frames, keys=['x', 'y'])

df_keys
    id Fonctionnalité1 Fonctionnalité2
x 0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J
y 0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T

La mention des clés permet également de retrouver facilement les données correspondant à un DataFrame particulier. Vous pouvez récupérer les données du DataFrame df2 dont l'étiquette est y en utilisant la méthode loc :

df_keys.loc['y']
  id Fonctionnalité1 Fonctionnalité2
0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T

Vous pouvez également passer un dictionnaire à concat(), auquel cas les clés du dictionnaire seront utilisées pour l'argument keys (à moins que d'autres clés ne soient spécifiées) :

pieces = {'x': df1, 'y': df2}

df_piece = pd.concat(pieces)

df_piece
    id Fonctionnalité1 Fonctionnalité2
x 0 1 A B
1 2 C D
2 3 E F
3 4 G H
4 5 I J
y 0 1 K L
1 2 M N
2 6 O P
3 7 Q R
4 8 S T

Il convient de noter que concat() effectue une copie complète des données et que la réutilisation continue de cette fonction peut nuire considérablement aux performances. Si vous devez utiliser l'opération sur plusieurs ensembles de données, utilisez une liste de compréhension.

frames = [ process_your_file(f) for f in files ]
result = pd.concat(frames)

Pour concaténer des DataFrames le long d'une colonne, vous pouvez spécifier que le paramètre d'axe est 1 :

df_col = pd.concat([df1,df2], axis=1)

df_col
  id Fonctionnalité1 Fonctionnalité2 id Fonctionnalité1 Fonctionnalité2
0 1 A B 1 K L
1 2 C D 2 M N
2 3 E F 6 O P
3 4 G H 7 Q R
4 5 I J 8 S T

pandas Merge DataFrame

Une autre opération omniprésente liée aux DataFrames est l'opération de fusion. Deux DataFrame peuvent contenir différents types d'informations sur la même entité et être liés par une caractéristique/colonne commune. Pour joindre ces DataFrame, pandas fournit de multiples fonctions comme concat(), merge() , join(), etc. Dans cette section, vous allez vous entraîner à utiliser la fonction merge() de pandas.

Vous pouvez joindre les DataFrame df_row (que vous avez créés en concaténant df1 et df2 le long de la ligne) et df3 sur la colonne commune (ou clé) id. Pour ce faire, transmettez les noms des DataFrame et un argument supplémentaire comme le nom de la colonne commune, ici id, à la fonction merge() :

df_merge_col = pd.merge(df_row, df3, on='id')

df_merge_col
  id Fonctionnalité1 Fonctionnalité2 Fonctionnalité3
0 1 A B 12
1 1 K L 12
2 2 C D 13
3 2 M N 13
4 3 E F 14
5 4 G H 15
6 5 I J 16
7 7 Q R 17
8 8 S T 15

Vous pouvez remarquer que les DataFrames sont maintenant fusionnées en une seule DataFrame sur la base des valeurs communes présentes dans la colonne id des deux DataFrames. Par exemple, la valeur d'identification 1 était présente à la fois avec A, B et K, L dans le DataFrame df_row. Cet identifiant a donc été répété deux fois dans le DataFrame final df_merge_col avec la valeur répétée 12 de Feature3 provenant du DataFrame df3.

Il peut arriver que les colonnes sur lesquelles vous souhaitez fusionner les DataFrame aient des noms différents (contrairement à ce qui se passe dans ce cas). Pour de telles fusions, vous devrez spécifier les arguments left_on comme nom du DataFrame de gauche et right_on comme nom du DataFrame de droite, comme :

df_merge_difkey = pd.merge(df_row, df3, left_on='id', right_on='id')

df_merge_difkey
  id Fonctionnalité1 Fonctionnalité2 Fonctionnalité3
0 1 A B 12
1 1 K L 12
2 2 C D 13
3 2 M N 13
4 3 E F 14
5 4 G H 15
6 5 I J 16
7 7 Q R 17
8 8 S T 15

Vous pouvez également ajouter des lignes à un DataFrame en passant une série ou un dict à la fonction append() qui renvoie un nouveau DataFrame :

add_row = pd.Series(['10', 'X1', 'X2', 'X3'],
                    index=['id','Feature1', 'Feature2', 'Feature3'])

df_add_row = df_merge_col.append(add_row, ignore_index=True)

df_add_row
  id Fonctionnalité1 Fonctionnalité2 Fonctionnalité3
0 1 A B 12
1 1 K L 12
2 2 C D 13
3 2 M N 13
4 3 E F 14
5 4 G H 15
6 5 I J 16
7 7 Q R 17
8 8 S T 15
9 10 X1 X2 X3

Types de pandas Rejoindre

Dans cette section, vous pratiquerez les différentes logiques de jointure disponibles pour fusionner des DataFrame pandas sur la base d'une colonne/clé commune. La logique qui sous-tend ces jointures est très proche de celle que vous avez en SQL lorsque vous joignez des tableaux.

Jointure externe complète

Le FULL OUTER JOIN combine les résultats des jointures externes de gauche et de droite. Le DataFrame joint contiendra tous les enregistrements des deux DataFrames et remplira les NaN pour les correspondances manquantes de part et d'autre. Vous pouvez effectuer une jointure externe complète en spécifiant l'argument how comme outer dans la fonction merge() :

df_outer = pd.merge(df1, df2, on='id', how='outer')

df_outer
  id Feature1_x Feature2_x Caractéristique1_y Feature2_y
0 1 A B K L
1 2 C D M N
2 3 E F NaN NaN
3 4 G H NaN NaN
4 5 I J NaN NaN
5 6 NaN NaN O P
6 7 NaN NaN Q R
7 8 NaN NaN S T

Vous pouvez remarquer que le DataFrame résultant contient toutes les entrées des deux tableaux avec des valeurs NaN pour les correspondances manquantes de part et d'autre. Cependant, une autre chose à remarquer est le suffixe qui a été ajouté aux noms des colonnes pour indiquer quelle colonne provient de quel DataFrame. Les suffixes par défaut sont x et y, mais vous pouvez les modifier en spécifiant l'argument suffixes dans la fonction merge() :

df_suffix = pd.merge(df1, df2, left_on='id',right_on='id',how='outer',suffixes=('_left','_right'))

df_suffix
  id Caractéristique1_gauche Caractéristique2_gauche Fonctionnalité1_droite Fonctionnalité2_droite
0 1 A B K L
1 2 C D M N
2 3 E F NaN NaN
3 4 G H NaN NaN
4 5 I J NaN NaN
5 6 NaN NaN O P
6 7 NaN NaN Q R
7 8 NaN NaN S T

Jointure interne

La jointure interne (INNER JOIN) ne produit que l'ensemble des enregistrements qui correspondent à la fois dans le DataFrame A et dans le DataFrame B. Vous devez indiquer inner dans l'argument how de la fonction merge() pour effectuer une jointure interne :

df_inner = pd.merge(df1, df2, on='id', how='inner')

df_inner
  id Feature1_x Feature2_x Caractéristique1_y Feature2_y
0 1 A B K L
1 2 C D M N

Droit Rejoindre

La JONCTION À DROITE produit un ensemble complet d'enregistrements du DataFrame B (DataFrame de droite), avec les enregistrements correspondants (le cas échéant) dans le DataFrame A (DataFrame de gauche). S'il n'y a pas de correspondance, le côté droit contiendra null. Vous devez passer right dans l'argument how de la fonction merge() pour effectuer une jointure right :

df_right = pd.merge(df1, df2, on='id', how='right')

df_right
  id Feature1_x Feature2_x Caractéristique1_y Feature2_y
0 1 A B K L
1 2 C D M N
2 6 NaN NaN O P
3 7 NaN NaN Q R
4 8 NaN NaN S T

Joint gauche

La jointure gauche produit un ensemble complet d'enregistrements du DataFrame A (DataFrame gauche), avec les enregistrements correspondants (le cas échéant) dans le DataFrame B (DataFrame droit). S'il n'y a pas de correspondance, le côté gauche contiendra null. Vous devez passer left dans l'argument how de la fonction merge() pour effectuer une jointure à gauche :

df_left = pd.merge(df1, df2, on='id', how='left')

df_left
  id Feature1_x Feature2_x Caractéristique1_y Feature2_y
0 1 A B K L
1 2 C D M N
2 3 E F NaN NaN
3 4 G H NaN NaN
4 5 I J NaN NaN

Jointure sur l'index

Parfois, vous devrez effectuer la jointure sur les index ou les étiquettes de ligne. Pour ce faire, vous devez spécifier right_index (pour les index du DataFrame de droite) et left_index (pour les index du DataFrame de gauche) comme True :

df_index = pd.merge(df1, df2, right_index=True, left_index=True)

df_index
  id_x Feature1_x Feature2_x id_y Caractéristique1_y Feature2_y
0 1 A B 1 K L
1 2 C D 2 M N
2 3 E F 6 O P
3 4 G H 7 Q R
4 5 I J 8 S T

pandas Rejoindre

La fonction Pandas DataFrame.join est utilisée pour joindre des cadres de données sur des index uniques. Vous pouvez utiliser l'argument optionnel `on` pour joindre les noms de colonne(s) sur l'index et comment les arguments gèrent l'opération des deux objets. Par défaut, il utilise la jointure interne. 

pandas Joindre deux DataFrame

Joignons deux cadres de données à l'aide de .join. Nous avons fourni `lsuffix` et `rsuffix` pour éviter l'erreur de chevauchement de colonnes. La jointure est basée sur l'index et non sur la colonne. Nous devons donc soit modifier la colonne "id", soit fournir un suffixe.

df2.join(df3, lsuffix='_left', rsuffix='_right')

  id_left Fonctionnalité1 Fonctionnalité2 id_right Fonctionnalité3
0 1 K L 1 12
1 2 M N 2 13
2 6 O P 3 14
3 7 Q R 4 15
4 8 S T 5 16

Nous pouvons également joindre des colonnes sur l'index en utilisant l'argument `on`. Pour appliquer la jointure avec succès, nous devons ajouter la colonne 'id' à l'index et fournir l'argument `on` avec la colonne 'id'. Par défaut, il utilisera la jointure gauche.   

df2.join(df3.set_index('id'), on='id')

  id Fonctionnalité1 Fonctionnalité2 Fonctionnalité3
0 1 K L 12.0
1 2 M N 13.0
2 6 O P NaN
3 7 Q R 17.0
4 8 S T 15.0

Tout comme la fonction merge, nous pouvons modifier le fonctionnement de join en fournissant un argument `how`. Dans notre cas, nous utiliserons une jointure interne. 

df2.join(df3.set_index('id'), on='id', how = "inner")

  id_left Fonctionnalité1 Fonctionnalité2 Fonctionnalité3
0 1 K L 12
1 2 M N 13
3 7 Q R 17
4 8 S T 15

Fusion conviviale de séries temporelles

Pandas propose des fonctions spéciales pour fusionner des DataFrame de séries temporelles. La fonction merge_asof() est peut-être la plus utile et la plus populaire. La fonction merge_asof() est similaire à une jointure gauche ordonnée, à ceci près que la correspondance se fait sur la clé la plus proche plutôt que sur les clés égales. Pour chaque ligne du DataFrame de gauche, vous sélectionnez la dernière ligne du DataFrame de droite dont la clé on est inférieure à la clé de gauche. Les deux DataFrame doivent être triés par la clé.

En option, une fusion asof peut effectuer une fusion par groupe. Cela correspond à la touche by de la même manière, en plus de la correspondance la plus proche sur la touche on.

Par exemple, vous pouvez avoir des transactions et des cotations et vous souhaitez les fusionner. Ici, le DataFrame de gauche est choisi pour les transactions et le DataFrame de droite pour les cotations. Ils sont actuellement fusionnés à l'heure de référence et regroupés par leur symbole boursier.

trades = pd.DataFrame({
    'time': pd.to_datetime(['20160525 13:30:00.023',
                            '20160525 13:30:00.038',
                            '20160525 13:30:00.048',
                            '20160525 13:30:00.048',
                            '20160525 13:30:00.048']),
    'ticker': ['MSFT', 'MSFT','GOOG', 'GOOG', 'AAPL'],
    'price': [51.95, 51.95,720.77, 720.92, 98.00],
    'quantity': [75, 155,100, 100, 100]},
    columns=['time', 'ticker', 'price', 'quantity'])

quotes = pd.DataFrame({
    'time': pd.to_datetime(['20160525 13:30:00.023',
                            '20160525 13:30:00.023',
                            '20160525 13:30:00.030',
                            '20160525 13:30:00.041',
                            '20160525 13:30:00.048',
                            '20160525 13:30:00.049',
                            '20160525 13:30:00.072',
                            '20160525 13:30:00.075']),
    'ticker': ['GOOG', 'MSFT', 'MSFT','MSFT', 'GOOG', 'AAPL', 'GOOG','MSFT'],
    'bid': [720.50, 51.95, 51.97, 51.99,720.50, 97.99, 720.50, 52.01],
    'ask': [720.93, 51.96, 51.98, 52.00,720.93, 98.01, 720.88, 52.03]},
    columns=['time', 'ticker', 'bid', 'ask'])
trades
  temps téléscripteur prix quantité
0 2016-05-25 13:30:00.023 MSFT 51.95 75
1 2016-05-25 13:30:00.038 MSFT 51.95 155
2 2016-05-25 13:30:00.048 GOOG 720.77 100
3 2016-05-25 13:30:00.048 GOOG 720.92 100
4 2016-05-25 13:30:00.048 AAPL 98.00 100
quotes
  temps téléscripteur offre demander
0 2016-05-25 13:30:00.023 GOOG 720.50 720.93
1 2016-05-25 13:30:00.023 MSFT 51.95 51.96
2 2016-05-25 13:30:00.030 MSFT 51.97 51.98
3 2016-05-25 13:30:00.041 MSFT 51.99 52.00
4 2016-05-25 13:30:00.048 GOOG 720.50 720.93
5 2016-05-25 13:30:00.049 AAPL 97.99 98.01
6 2016-05-25 13:30:00.072 GOOG 720.50 720.88
7 2016-05-25 13:30:00.075 MSFT 52.01 52.03
df_merge_asof = pd.merge_asof(trades, quotes,
              on='time',
              by='ticker')

df_merge_asof
  temps téléscripteur prix quantité offre demander
0 2016-05-25 13:30:00.023 MSFT 51.95 75 51.95 51.96
1 2016-05-25 13:30:00.038 MSFT 51.95 155 51.97 51.98
2 2016-05-25 13:30:00.048 GOOG 720.77 100 720.50 720.93
3 2016-05-25 13:30:00.048 GOOG 720.92 100 720.50 720.93
4 2016-05-25 13:30:00.048 AAPL 98.00 100 NaN NaN

Si vous observez attentivement, vous pouvez remarquer la raison pour laquelle NaN apparaît dans la ligne du téléscripteur AAPL. Comme les cotations du DataFrame de droite n'avaient pas de valeur temporelle inférieure à 13:30:00.048 (l'heure dans le tableau de gauche) pour le téléscripteur AAPL, des NaN ont été introduits dans les colonnes d'offre et de demande.

Vous pouvez également définir un niveau de tolérance prédéfini pour la colonne de temps. Supposons que vous souhaitiez uniquement une fusion asof dans les 2ms entre l'heure de cotation et l'heure de négociation, vous devrez alors spécifier l'argument de la tolérance :

df_merge_asof_tolerance = pd.merge_asof(trades, quotes,
              on='time',
              by='ticker',
              tolerance=pd.Timedelta('2ms'))

df_merge_asof_tolerance
  temps téléscripteur prix quantité offre demander
0 2016-05-25 13:30:00.023 MSFT 51.95 75 51.95 51.96
1 2016-05-25 13:30:00.038 MSFT 51.95 155 NaN NaN
2 2016-05-25 13:30:00.048 GOOG 720.77 100 720.50 720.93
3 2016-05-25 13:30:00.048 GOOG 720.92 100 720.50 720.93
4 2016-05-25 13:30:00.048 AAPL 98.00 100 NaN NaN

Remarquez la différence entre le résultat ci-dessus et le résultat précédent. Les lignes ne sont pas fusionnées si la tolérance temporelle ne correspond pas à 2 ms.

Conclusion

Dans ce tutoriel, vous avez appris à concaténer et à fusionner des DataFrame basés sur plusieurs logiques à l'aide des fonctions concat() et merge() de la bibliothèque pandas. Vers la fin, vous avez également pratiqué la fonction spéciale merge_asof() pour fusionner des DataFrames de séries temporelles. En cours de route, vous avez également appris à jouer avec les index des DataFrame. Il existe plusieurs autres options que vous pouvez explorer pour joindre des DataFrame dans pandas, et je vous encourage à consulter sa fantastique documentation. Bonne exploration !

Ce tutoriel s'est appuyé sur la documentation de pandas.

Si vous souhaitez en savoir plus sur les pandas, suivez le cours de DataCamp sur les fondements des pandas et consultez notre tutoriel DataFrames in Python Pandas.

DataCamp propose également plusieurs autres tutoriels pandas très pratiques :

Bon apprentissage !

Sujets

En savoir plus sur Python et pandas

Certification disponible

cours

Pandas Joins pour les utilisateurs de tableurs

4 hr
3.6K
Apprenez à joindre efficacement des ensembles de données sous forme de tableaux à l'aide de la bibliothèque Python Pandas.
Afficher les détailsRight Arrow
Commencer Le Cours
Voir plusRight Arrow