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.
· 13 min lire

Explorez l'IA

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
 idFonctionnalité1Fonctionnalité2
01AB
12CD
23EF
34GH
45IJ

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
 idFonctionnalité1Fonctionnalité2
01KL
12MN
26OP
37QR
48ST
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
 idFonctionnalité3
0112
1213
2314
3415
4516
5717
6815
7912
81013
91123

 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
 idFonctionnalité1Fonctionnalité2
01AB
12CD
23EF
34GH
45IJ
01KL
12MN
26OP
37QR
48ST

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
 idFonctionnalité1Fonctionnalité2
01AB
12CD
23EF
34GH
45IJ
51KL
62MN
76OP
87QR
98ST

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
  idFonctionnalité1Fonctionnalité2
x01AB
12CD
23EF
34GH
45IJ
y01KL
12MN
26OP
37QR
48ST

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']
 idFonctionnalité1Fonctionnalité2
01KL
12MN
26OP
37QR
48ST

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
  idFonctionnalité1Fonctionnalité2
x01AB
12CD
23EF
34GH
45IJ
y01KL
12MN
26OP
37QR
48ST

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
 idFonctionnalité1Fonctionnalité2idFonctionnalité1Fonctionnalité2
01AB1KL
12CD2MN
23EF6OP
34GH7QR
45IJ8ST

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
 idFonctionnalité1Fonctionnalité2Fonctionnalité3
01AB12
11KL12
22CD13
32MN13
43EF14
54GH15
65IJ16
77QR17
88ST15

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
 idFonctionnalité1Fonctionnalité2Fonctionnalité3
01AB12
11KL12
22CD13
32MN13
43EF14
54GH15
65IJ16
77QR17
88ST15

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
 idFonctionnalité1Fonctionnalité2Fonctionnalité3
01AB12
11KL12
22CD13
32MN13
43EF14
54GH15
65IJ16
77QR17
88ST15
910X1X2X3

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
 idFeature1_xFeature2_xCaractéristique1_yFeature2_y
01ABKL
12CDMN
23EFNaNNaN
34GHNaNNaN
45IJNaNNaN
56NaNNaNOP
67NaNNaNQR
78NaNNaNST

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
 idCaractéristique1_gaucheCaractéristique2_gaucheFonctionnalité1_droiteFonctionnalité2_droite
01ABKL
12CDMN
23EFNaNNaN
34GHNaNNaN
45IJNaNNaN
56NaNNaNOP
67NaNNaNQR
78NaNNaNST

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
 idFeature1_xFeature2_xCaractéristique1_yFeature2_y
01ABKL
12CDMN

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
 idFeature1_xFeature2_xCaractéristique1_yFeature2_y
01ABKL
12CDMN
26NaNNaNOP
37NaNNaNQR
48NaNNaNST

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
 idFeature1_xFeature2_xCaractéristique1_yFeature2_y
01ABKL
12CDMN
23EFNaNNaN
34GHNaNNaN
45IJNaNNaN

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_xFeature1_xFeature2_xid_yCaractéristique1_yFeature2_y
01AB1KL
12CD2MN
23EF6OP
34GH7QR
45IJ8ST

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_leftFonctionnalité1Fonctionnalité2id_rightFonctionnalité3
01KL112
12MN213
26OP314
37QR415
48ST516

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')

 idFonctionnalité1Fonctionnalité2Fonctionnalité3
01KL12.0
12MN13.0
26OPNaN
37QR17.0
48ST15.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_leftFonctionnalité1Fonctionnalité2Fonctionnalité3
01KL12
12MN13
37QR17
48ST15

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
 tempstéléscripteurprixquantité
02016-05-25 13:30:00.023MSFT51.9575
12016-05-25 13:30:00.038MSFT51.95155
22016-05-25 13:30:00.048GOOG720.77100
32016-05-25 13:30:00.048GOOG720.92100
42016-05-25 13:30:00.048AAPL98.00100
quotes
 tempstéléscripteuroffredemander
02016-05-25 13:30:00.023GOOG720.50720.93
12016-05-25 13:30:00.023MSFT51.9551.96
22016-05-25 13:30:00.030MSFT51.9751.98
32016-05-25 13:30:00.041MSFT51.9952.00
42016-05-25 13:30:00.048GOOG720.50720.93
52016-05-25 13:30:00.049AAPL97.9998.01
62016-05-25 13:30:00.072GOOG720.50720.88
72016-05-25 13:30:00.075MSFT52.0152.03
df_merge_asof = pd.merge_asof(trades, quotes,
              on='time',
              by='ticker')

df_merge_asof
 tempstéléscripteurprixquantitéoffredemander
02016-05-25 13:30:00.023MSFT51.957551.9551.96
12016-05-25 13:30:00.038MSFT51.9515551.9751.98
22016-05-25 13:30:00.048GOOG720.77100720.50720.93
32016-05-25 13:30:00.048GOOG720.92100720.50720.93
42016-05-25 13:30:00.048AAPL98.00100NaNNaN

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
 tempstéléscripteurprixquantitéoffredemander
02016-05-25 13:30:00.023MSFT51.957551.9551.96
12016-05-25 13:30:00.038MSFT51.95155NaNNaN
22016-05-25 13:30:00.048GOOG720.77100720.50720.93
32016-05-25 13:30:00.048GOOG720.92100720.50720.93
42016-05-25 13:30:00.048AAPL98.00100NaNNaN

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

Contenus associés