Réunissez deux tables comme il faut — choisissez la jointure d’après votre question, validez la clé, et ne perdez ni ne dupliquez jamais une ligne en silence.
Combinez deux DataFrames pandas en un seul : pd.merge avec les jointures inner, left, right et outer choisies selon la question, fusion sur des clés aux noms différents avec left_on/right_on, validation de la clé avec validate= et indicator=, gestion des colonnes en doublon avec suffixes=, et empilement de tables avec pd.concat versus df.join.
Date de publication
17 juillet 2026
Modifié
18 juillet 2026
AstucePoints clés
Deux tables qui partagent une clé n’en forment plus qu’une avec pd.merge.pd.merge(left, right, on="key", how=...) aligne les lignes en faisant correspondre les valeurs de la clé — la réponse pandas au JOIN de SQL.
how= décide quelles lignes survivent.inner ne garde que les correspondances, left garde chaque ligne de gauche (le choix par défaut au quotidien pour l’enrichissement), right garde chaque ligne de droite, outer garde tout. Vérifiez toujours .shape avant et après.
Validez la clé, sinon la fusion vous ment en silence.validate="many_to_one" lève une erreur si la clé n’est pas unique à droite ; indicator=True ajoute une colonne _merge pour que vous voyiez les lignes sans correspondance — la meilleure habitude de fusion qui soit.
left_on/right_on fusionnent sur des clés aux noms différents ; suffixes= renomme les colonnes en doublon. Un _x/_y silencieux sur vos colonnes signifie que les deux tables portaient le même nom — étiquetez-les à dessein.
concat empile, merge aligne.pd.concat empile les tables les unes sur les autres (mêmes colonnes, plus de lignes) ; merge accole des colonnes différentes côte à côte via une clé. df.join est un merge sur l’index.
Introduction
Les données réelles arrivent rarement dans une seule table. Vous avez les mesures corporelles des manchots dans un fichier et, dans un autre, des informations de référence sur les îles où ils ont été capturés — la région, la latitude, la station de terrain. Aucune table seule ne peut répondre à « les manchots sont-ils plus lourds au sud ? » : la masse est dans l’une, la latitude dans l’autre. Les combiner est le geste à faire, et en pandas cela signifie merge, join et concat.
Cette leçon, c’est la boîte à outils de la combinaison telle que vous l’utilisez vraiment : charger les deux tables, les merge sur leur clé commune, choisir le type de jointure d’après la question que vous posez, puis vous prémunir contre le désastre classique de la fusion — une clé qui fait correspondre les mauvaises lignes en silence, ou aucune. Vous validerez la fusion, gérerez des clés aux noms différents et des colonnes portant le même nom, et finirez en empilant des tables avec concat quand une jointure n’est pas ce que vous voulez.
C’est la couche suivante par-dessus les DataFrames pandas, qui couvrent le chargement, la sélection, le filtrage et groupby — on s’appuie dessus ici sans les réenseigner. Les deux tables sont livrées sous forme de petits CSV à côté de cette leçon (les mesures des manchots proviennent du jeu de données Palmer Station LTER / palmerpenguins), donc rien à télécharger et aucun réseau au rendu. Chaque résultat ci-dessous a été produit par le code affiché, et les blocs s’enchaînent dans l’ordre. Pour expérimenter, modifiez la cellule Essayez en direct à la fin et appuyez sur Run.
Les deux tables
Commencez par charger les deux et regarder chacune. penguins est la grande table de mesures — une ligne par oiseau ; islands est une petite table de référence (ou de correspondance) — une ligne par île, portant des faits que vous voulez rattacher à chaque oiseau de cette île.
penguins: (344, 7)
species island body_mass_g
0 Adelie Torgersen 3750.0
1 Adelie Torgersen 3800.0
2 Adelie Torgersen 3250.0
print("islands:", islands.shape)print(islands)
islands: (3, 4)
island region latitude station
0 Biscoe South -64.82 Palmer Station
1 Dream North -64.73 Palmer Station
2 Torgersen North -64.77 Palmer Station
penguins a 344 lignes et 7 colonnes ; islands n’en a que 3 lignes et 4 colonnes — une par île, avec une region (un secteur nord/sud grossier que nous avons attribué par latitude), la latitude approximative de l’île et la station de terrain. Les deux tables partagent exactement une colonne, island — cette colonne commune est la clé sur laquelle nous allons fusionner. L’objectif : rattacher la region, la latitude et la station de chaque île à chaque manchot capturé là-bas.
pd.merge : rattacher la table de référence
Le cheval de bataille, c’est pd.merge(left, right, on=..., how=...). Il parcourt la table de gauche et, pour chaque ligne, trouve la ou les lignes de la table de droite dont la clé correspond, puis y accole leurs colonnes. Ici, nous rattachons islands à penguins, en faisant correspondre sur island :
before: (344, 7) after: (344, 10)
species island body_mass_g region latitude
0 Adelie Torgersen 3750.0 North -64.77
1 Adelie Torgersen 3800.0 North -64.77
2 Adelie Torgersen 3250.0 North -64.77
Lisez les shapes : 344 lignes en entrée, 344 lignes en sortie — aucun oiseau gagné ni perdu — et les colonnes sont passées de 7 à 10 (la clé island est partagée, donc seules les trois nouvelles colonnes region, latitude, station ont été ajoutées). Chaque Adélie de Torgersen porte désormais region="North" et latitude=-64.77. C’est l’enrichissement : une petite table de référence, diffusée à travers des milliers de lignes. C’est de loin la fusion que vous écrirez le plus souvent.
Pourquoi how="left" ? Parce que la question était « ajouter les faits des îles aux manchots » — vous voulez garder chaque ligne de manchot, que la référence ait son île ou non, et laisser simplement les colonnes supplémentaires vides quand ce n’est pas le cas. left garde chaque ligne de la table de gauche ; c’est pourquoi c’est le choix par défaut au quotidien pour rattacher une table de correspondance. La section suivante montre ce que font les autres choix.
Les quatre jointures : inner, left, right, outer
how= choisit quelles lignes survivent quand les clés ne s’alignent pas parfaitement — et chaque choix répond à une question différente. Pour voir la différence, il nous faut un décalage de clé, alors voici une référence délibérément imparfaite : il lui manque Dream, et elle liste Anvers (une île réelle où ce jeu de données n’a par hasard capturé aucun manchot).
island region latitude
0 Biscoe South -64.82
1 Torgersen North -64.77
2 Anvers North -64.77
Maintenant la même fusion sous chaque how=, en surveillant .shape. Il y a 344 manchots (Biscoe 168, Dream 124, Torgersen 52) ; seuls Biscoe et Torgersen figurent dans les deux tables.
shapes = {}for how in ["inner", "left", "right", "outer"]: shapes[how] = pd.merge(penguins, islands_ref, on="island", how=how).shapefor how, sh in shapes.items():print(f"{how:<6} -> {sh[0]} rows")
inner -> 220 rows
left -> 344 rows
right -> 221 rows
outer -> 345 rows
Chaque nombre raconte l’histoire :
inner — 220 lignes. Uniquement les îles présentes dans les deux tables (Biscoe 168 + Torgersen 52). Les manchots de Dream (pas de ligne de référence) et Anvers (pas de manchots) sont tous deux écartés. À utiliser quand vous ne voulez que des enregistrements pleinement appariés — mais sachez qu’il supprime en silence les 124 oiseaux de Dream.
left — 344 lignes. Chaque manchot (la table de gauche) ; les oiseaux de Dream sont gardés avec NaN dans region/latitude. Anvers n’apparaît jamais — il n’est pas dans la table de gauche. Le choix par défaut pour l’enrichissement.
right — 221 lignes. Chaque ligne de référence (la table de droite) : les 220 manchots appariés plus une ligne Anvers avec des colonnes de manchot à NaN. À utiliser quand c’est la table de droite que vous devez garder entière.
outer — 345 lignes. L’union : les 344 manchots et la ligne Anvers non appariée. Rien n’est écarté d’aucun des deux côtés.
Le piège à intégrer : inner est le choix par défaut dans la tête de beaucoup de gens, et il perd des lignes en silence. Passer cette fusion de left à inner aurait supprimé chaque manchot de Dream sans un mot. Choisissez la jointure d’après la question, et comparez toujours .shape avant et après.
Valider la fusion — attraper la mauvaise clé silencieuse
Une fusion peut s’exécuter proprement et être quand même fausse. Les deux échecs classiques sont une clé qui n’est pas unique là où vous le pensiez (les lignes se multiplient en silence) et des clés qui ne correspondent pas (les lignes disparaissent en silence). pandas vous donne un garde-fou pour chacun.
validate= affirme la cardinalité de la clé et lève une erreur si elle est violée. Notre table islands a une ligne par île, et de nombreux manchots par île — une fusion many-to-one — alors on peut le déclarer et laisser pandas l’imposer :
Elle passe en silence parce que island est unique dans islands. Si la référence avait accidentellement contenu Biscoe deux fois, validate="many_to_one" aurait levé MergeError au lieu de doubler silencieusement chaque manchot de Biscoe — le bug d’explosion de lignes qui gonfle les effectifs et les moyennes. Déclarez la relation que vous attendez ("one_to_one", "many_to_one", "one_to_many") et laissez la fusion la vérifier.
indicator=True ajoute une colonne _merge qui étiquette chaque ligne both, left_only ou right_only — pour que vous puissiez voir les non-correspondances au lieu de les traquer. Lancez-le contre la référence imparfaite pour trouver les oiseaux sans faits d’île :
Le décompte est sans ambiguïté : 220 both et 124 left_only — ces 124 sont les manchots de Dream qui manquent à la référence. En une ligne, vous avez trouvé exactement quelles lignes n’ont pas correspondu, avant qu’un seul NaN ne corrompe un calcul en aval. Ayez le réflexe indicator=True sur chaque fusion en laquelle vous n’avez pas pleinement confiance ; il transforme un échec silencieux en un nombre visible.
Clés aux noms différents : left_on / right_on
on="island" exige que la colonne de clé porte le même nom dans les deux tables. Souvent ce n’est pas le cas — une table dit island, une autre island_name. Plutôt que de renommer d’abord, pointez merge vers la clé de chaque côté avec left_on et right_on :
island island_name region
0 Torgersen Torgersen North
1 Torgersen Torgersen North
2 Torgersen Torgersen North
La correspondance se fait sur les valeurs, donc elle fonctionne très bien malgré les noms différents. Le seul hic : vous portez maintenant les deux colonnes de clé (island et island_name) — contenu identique, alors supprimez ensuite la redondante avec merged.drop(columns="island_name"). Quand les clés partagent déjà un nom, le simple on= est plus propre ; n’ayez recours à left_on/right_on que lorsqu’elles diffèrent.
Colonnes en doublon : suffixes=
Quand les deux tables ont une colonne non-clé portant le même nom, pandas ne peut pas garder les deux sous une seule étiquette, alors il ajoute _x (gauche) et _y (droite). C’est un signal pour les nommer vous-même. Ici, nous construisons deux résumés par île — longueur moyenne du bec au global, et pour les mâles seulement — qui nomment tous deux leur colonne bill_length_mm :
Les colonnes sont revenues sous les noms bill_length_mm_x et bill_length_mm_y — techniquement correct, mais vous ne vous souviendrez jamais laquelle est laquelle. Passez suffixes= pour les étiqueter de façon parlante :
Maintenant bill_length_mm_all et bill_length_mm_male disent ce qu’ils sont, et les nombres racontent une histoire nette : sur chaque île, la longueur moyenne du bec des mâles est plus grande que la moyenne globale (Biscoe 47.1 contre 45.3 mm, Dream 46.1 contre 44.2, Torgersen 40.6 contre 39.0) — parce que les mâles sont les plus grands oiseaux et tirent la moyenne « mâle » au-dessus de la moyenne d’ensemble. Un simple _x/_y sur vos colonnes fusionnées signale toujours un conflit de noms non géré ; définissez suffixes= à dessein.
concat : empiler des tables au lieu de les joindre
merge aligne des colonnes différentes côte à côte via une clé. Parfois vous voulez l’inverse : deux tables aux mêmes colonnes que vous empilez les unes sur les autres — les données du mois dernier et celles de ce mois-ci, ou un fichier par site. C’est pd.concat, et il empile les lignes :
Les 168 lignes de Biscoe et les 124 lignes de Dream s’empilent en 292 lignes avec les mêmes 7 colonnes. ignore_index=True renumérote le résultat de 0 à 291 au lieu de conserver les deux plages d’index d’origine (qui se répéteraient). C’est l’outil pour réassembler des données qui avaient été découpées — en concaténant des DataFrames par fichier après une boucle de read_csv, par exemple.
La distinction mérite d’être fixée dans votre esprit : ayez le réflexe concat quand les tables décrivent les mêmes choses (mêmes colonnes, plus de lignes) ; ayez le réflexe merge quand elles décrivent des choses différentes sur la même clé (colonnes différentes, alignées par une valeur correspondante). concat peut aussi coller des colonnes avec axis=1, mais il aligne sur l’index des lignes (la position), pas sur une clé — c’est précisément pourquoi merge est plus sûr pour combiner des colonnes : il fait correspondre sur la valeur de la clé, pas sur le fait que les lignes se trouvent dans le même ordre.
Un mot sur df.join
Vous verrez df.join dans le code des autres, et ce n’est qu’un merge spécialisé sur l’index. Il rattache une autre table en faisant correspondre sur l’index plutôt que sur une colonne. Mettez l’île comme index de la table de référence et join la lit directement :
joined = penguins.join(islands.set_index("island"), on="island")print(joined[["species", "island", "region", "latitude"]].head(3))
species island region latitude
0 Adelie Torgersen North -64.77
1 Adelie Torgersen North -64.77
2 Adelie Torgersen North -64.77
C’est le même enrichissement que notre premier pd.merge(..., how="left"), écrit index d’abord : join fait par défaut une jointure left et fait correspondre l’index de la table de droite à la colonne on= que vous nommez. C’est pratique quand la référence est déjà indexée par la clé, mais il ne fait rien que merge ne puisse faire — la plupart des gens s’en tiennent à pd.merge(..., on=...) pour un seul modèle mental explicite, fondé sur les colonnes. Apprenez à lirejoin ; ayez le réflexe merge pour écrire.
Le gain : une question qu’aucune table ne pouvait résoudre
Voici maintenant la raison pour laquelle nous avons fusionné. La masse corporelle est dans penguins ; la région et la latitude sont dans islands. Seule la table fusionnée peut répondre à « la masse corporelle varie-t-elle selon la région ? » — alors calculez la masse moyenne par île à partir du tableau enrichi et tracez-la, ordonnée du sud au nord et colorée par la région issue de la table de référence.
import matplotlib.pyplot as pltenriched = pd.merge(penguins, islands, on="island", how="left")by_island = ( enriched.dropna(subset=["body_mass_g"]) .groupby(["island", "region", "latitude"], as_index=False)["body_mass_g"] .mean() .sort_values("latitude") # south (most negative) -> north)REGION_COLORS = {"South": "#3a86d4", "North": "#f4a259"}bar_colors = [REGION_COLORS[r] for r in by_island["region"]]fig, ax = plt.subplots(figsize=(7, 4.5))ax.bar(by_island["island"], by_island["body_mass_g"], color=bar_colors, width=0.65)for x, v inzip(by_island["island"], by_island["body_mass_g"]): ax.text(x, v +40, f"{v:.0f}", ha="center", va="bottom", fontsize=9)ax.set_xlabel("Island (south → north)")ax.set_ylabel("Mean body mass (g)")ax.set_title("Mean penguin body mass by island and region")ax.spines[["top", "right"]].set_visible(False)handles = [plt.Rectangle((0, 0), 1, 1, color=c) for c in REGION_COLORS.values()]ax.legend(handles, REGION_COLORS.keys(), title="Region", frameon=False)fig.tight_layout()plt.show()
Figure 1
La figure répond à la question que les deux tables ne pouvaient pas résoudre séparément. Biscoe, la seule île du sud, est bien plus lourde — masse corporelle moyenne ~4716 g contre ~3706 g (Torgersen) et ~3713 g (Dream) au nord. La lecture honnête n’est pas « le sud rend les manchots lourds » ; c’est que Biscoe est là où vivent les grands manchots Gentoo, et la fusion est ce qui nous a permis d’aligner la géographie sur la masse pour le voir. La region et la latitude sur l’axe des x et dans les couleurs venaient entièrement de islands.csv — impossible à tracer sans la jointure.
Quelle combinaison pour quelle question ?
Choisissez l’outil d’après ce que vous combinez, pas par habitude :
Votre situation
L’outil
L’appel
Rattacher des faits de référence à une grande table (garder chaque ligne)
Merge left
pd.merge(df, ref, on="key", how="left")
Ne garder que les lignes présentes dans les deux tables
Merge inner
pd.merge(a, b, on="key", how="inner")
Tout garder des deux tables
Merge outer
pd.merge(a, b, on="key", how="outer")
Les colonnes de clé ont des noms différents
left_on/right_on
pd.merge(a, b, left_on="id", right_on="ID")
Les deux tables partagent un nom de colonne non-clé
suffixes=
pd.merge(a, b, on="key", suffixes=("_a", "_b"))
Empiler des tables aux mêmes colonnes (plus de lignes)
concat
pd.concat([df1, df2], ignore_index=True)
Combiner par l’index plutôt que par une colonne
join
a.join(b.set_index("key"), on="key")
En cas de doute : colonnes différentes sur la même clé → merge ; mêmes colonnes, plus de lignes → concat. Et quel que soit votre choix, vérifiez .shape avant et après et lancez indicator=True si vous n’êtes pas certain que les clés correspondent.
La même idée en R
Vous travaillez en R, ou dans les deux langages ? L’équivalent se trouve dans la série Manipulation de données en R (dplyr) : pd.merge(..., how="left") correspond au left_join() de dplyr, inner à inner_join(), outer à full_join(), et pd.concat (lignes) à bind_rows(). Les concepts se transfèrent directement — une colonne de clé, un type de jointure, et le même soin quant aux lignes qui survivent.
Essayez en direct
Les blocs ci-dessus se sont exécutés au moment du build. Modifiez celui-ci et appuyez sur Run pour fusionner les deux tables vous-même — il s’exécute dans votre navigateur via Pyodide (aucune installation). Le premier Run télécharge pandas une fois (~20 Mo), puis c’est mis en cache et instantané.
🟢 Avec un agent IA
Vous avez deux CSV à combiner ? Collez un df.head() de chacun et demandez à Prova« quelle jointure me faut-il, et quel est l’appel pd.merge — et comment vérifier qu’aucune ligne n’a été perdue ni dupliquée en silence ? » Elle choisit how= d’après votre question, écrit l’appel on=/left_on=/right_on=, et ajoute les garde-fous validate= et indicator=True. Parce que le runtime est juste là, vous l’exécutez et lisez le .shape et les décomptes _merge vous-même, au lieu de faire confiance à une fusion qui a l’air correcte mais a discrètement perdu la moitié de vos lignes. The runtime is the judge. Demander à Prova →
Problèmes fréquents
Votre nombre de lignes a explosé après une fusion. Une fusion sur une clé qui n’est pas unique à droite produit en silence chaque combinaison gauche×droite — une explosion many-to-many qui gonfle les effectifs et les moyennes. Si pd.merge(a, b, on="id") renvoie bien plus de lignes que n’en avait a, c’est que la table de droite a des clés en double. Prémunissez-vous en amont avec validate="many_to_one" (il lève une erreur au lieu de multiplier), et dédoublonnez la référence avec b.drop_duplicates("id") si les lignes en trop sont accidentelles.
Des lignes ont disparu en silence. C’est une jointure inner (souvent celle par défaut dans votre tête) qui écarte chaque ligne dont la clé n’est pas dans les deux tables. Passez à how="left" pour garder toute la table de gauche, et lancez d’abord indicator=True pour voir exactement quelles clés ne correspondent pas — un décompte left_only est le nombre de lignes qu’une jointure inner aurait supprimées.
Des NaN inattendus dans les colonnes fusionnées. Après une fusion left (ou outer), les lignes dont la clé n’avait aucune correspondance à droite reviennent avec NaN dans les colonnes ajoutées — c’est la jointure qui fonctionne correctement, en vous disant que la référence était incomplète. Trouvez-les avec merged[merged["region"].isna()] (ou indicator=True), puis décidez : corriger la clé (un décalage d’espace ou de casse — "Biscoe " ≠ "Biscoe"), combler le trou avec fillna, ou accepter les lignes manquantes.
Les colonnes sont revenues sous _x et _y. Les deux tables portaient le même nom de colonne non-clé et pandas les a désambiguïsées pour vous. Passez suffixes=("_left", "_right") (ou mieux, des étiquettes parlantes) pour pouvoir les distinguer — ou supprimez/renommez une colonne avant la fusion si vous n’en avez besoin que d’une.
Questions fréquentes
NoteQuelle est la différence entre merge et join dans pandas ?
Ils font le même travail — combiner deux tables — mais font correspondre sur des choses différentes. pd.merge (ou df.merge) fait correspondre sur les colonnes que vous nommez avec on=/left_on=/right_on=, et c’est l’outil général et explicite qu’utilise la plupart du code. df.join fait correspondre sur l’index par défaut (ou une colonne que vous passez avec on=), c’est donc une commodité pour quand la table de droite est déjà indexée par la clé. Tout ce que fait join, merge peut le faire ; tenez-vous-en à merge pour un seul modèle mental clair.
NoteComment faire une jointure left dans pandas ?
Passez how="left" : pd.merge(left, right, on="key", how="left"). Il garde chaque ligne de la table de gauche et y accole les colonnes correspondantes de la droite, en remplissant NaN là où la droite n’a aucune correspondance. C’est le choix par défaut pour l’enrichissement — ajouter des colonnes de référence/correspondance à une table sans en perdre aucune ligne. Vérifiez .shape après : le nombre de lignes doit être égal à celui de la table de gauche.
NoteComment fusionner deux DataFrames sur plusieurs colonnes ?
Passez une liste à on= : pd.merge(a, b, on=["year", "country"]). pandas fait correspondre les lignes où toutes les clés listées sont égales — le choix naturel quand une seule colonne n’est pas un identifiant unique mais qu’une combinaison l’est (par exemple une valeur par année et pays). Si les colonnes de clé ont des noms différents de chaque côté, utilisez plutôt des listes avec left_on= et right_on= : left_on=["yr", "cc"], right_on=["year", "country"].
NoteÀ quoi sert indicator=True dans une fusion pandas ?
Il ajoute une colonne catégorielle nommée _merge qui étiquette chaque ligne de sortie both, left_only ou right_only, pour que vous puissiez voir quelles lignes ont correspondu et lesquelles non. Lancez merged["_merge"].value_counts() juste après la fusion : un décompte left_only ou right_only non nul est le nombre de lignes qui n’ont pas correspondu — le moyen le plus rapide d’attraper une clé défectueuse avant qu’elle ne corrompe un calcul.
NoteQuand utiliser concat plutôt que merge ?
Utilisez pd.concat quand les tables ont les mêmes colonnes et que vous voulez les empiler en plus de lignes — réassembler des données découpées par fichier, par mois ou par site. Utilisez merge quand les tables ont des colonnes différentes décrivant la même clé et que vous voulez les aligner côte à côte. Règle empirique : mêmes colonnes, plus de lignes → concat ; colonnes différentes, alignées par une clé → merge.
Testez vos connaissances
ImportantÀ vous de jouer — combiner et valider
Utilisez les deux tables dans la cellule Essayez en direct ci-dessus (penguins = pd.read_csv("penguins.csv"), islands = pd.read_csv("islands.csv")).
Tâche 1. Fusionnez islands sur penguins avec une jointure left, puis indiquez combien de manchots ont fini dans chaque region. Confirmez qu’aucune ligne n’a été perdue.
AstuceIndice
pd.merge(penguins, islands, on="island", how="left"), puis ["region"].value_counts(). Comparez le .shape[0] fusionné au penguins.shape[0] — ils doivent correspondre.
Le nombre de lignes reste 344 (une jointure left garde chaque manchot), et les régions se répartissent en North 176 / South 168 — Biscoe (168 oiseaux) est la seule île du sud, le reste est au nord.
Tâche 2. Construisez une référence à laquelle il manque Dream et fusionnez-la avec indicator=True. Combien de manchots reviennent en left_only, et de quelle île sont-ils ?
124 lignes reviennent en left_only — chaque manchot de Dream, puisque la référence n’a plus de ligne Dream à faire correspondre. indicator=True nomme l’échec au lieu de vous laisser repérer les NaN.
Vérification rapide. Vous fusionnez une table de mesures de 500 lignes sur une référence et récupérez 1 300 lignes. Que s’est-il presque certainement passé ?
AstuceAfficher la réponse
La clé n’est pas unique à droite — la référence a des valeurs de clé en double, donc chaque ligne de gauche a correspondu à plusieurs lignes de droite (une explosion many-to-many). Ajoutez validate="many_to_one" pour faire lever la fusion au lieu de multiplier, et drop_duplicates la référence si les lignes en trop sont accidentelles. Une fusion qui fait grossir la table de gauche est le signe révélateur d’une clé dupliquée.
Conclusion
Vous savez maintenant réunir deux tables en une seule comme le travail l’exige : pd.merge sur une clé commune, le type de jointure (inner/left/right/outer) choisi d’après la question et sa conséquence sur le nombre de lignes, left_on/right_on pour des noms de clé discordants, et suffixes= pour des colonnes en conflit. Tout aussi important, vous pouvez faire confiance au résultat — validate= protège du bug d’explosion de lignes et indicator=True fait remonter les non-correspondances avant qu’elles ne deviennent des NaN silencieux. Et vous savez quand une jointure est le mauvais outil : mêmes colonnes et plus de lignes appellent concat, pas merge. Entraînez-vous sur vos deux tables à vous, en vérifiant toujours .shape avant et après, et l’étape de combinaison cesse d’être l’endroit où les analyses cassent en silence.
Prouvez que vous savez le faire. Maîtrisez toute la série Manipulation de données en Python — suivez votre parcours, construisez des projets et obtenez un certificat.