Skip to content

Pandas Merge & Join : des joins SQL maîtrisés

Updated on

Les joins sont piégeux : clés mal alignées, lignes dupliquées ou perte silencieuse de données. how="inner" est souvent sur-utilisé et validate/indicator oubliés.

Cadre PAS :

  • Problème : Les merges multiplient les lignes ou en suppriment à cause de clés incorrectes.
  • Agiter : Déboguer les joins prend du temps—sufixes doublonnés, produits cartésiens inattendus, lignes manquantes.
  • Solution : Définir les clés explicitement, choisir le bon how, utiliser validate et ajouter indicator pour auditer rapidement.

Tableau mémo des joins

Type (how)Garde la gauche ?Garde la droite ?Usage typique
inner✅ seulement les matches✅ seulement les matchesIntersection
left✅ tout🚫 seulement matchesEnrichir la table de gauche
right🚫 seulement matches✅ toutEnrichir la droite (rare, mieux inverser)
outer✅ tout✅ toutUnion complète avec trous

Données d’exemple

import pandas as pd
 
orders = pd.DataFrame({
    "order_id": [1, 2, 3],
    "customer_id": [100, 101, 102],
    "amount": [50, 80, 60],
})
 
customers = pd.DataFrame({
    "customer_id": [100, 101, 103],
    "name": ["Ada", "Ben", "Cara"],
    "segment": ["pro", "basic", "pro"],
})

Merge de base sur une clé de colonne

result = orders.merge(
    customers,
    on="customer_id",
    how="left",
    validate="many_to_one",  # table dimension attendue
    indicator=True,          # audit de couverture
)
  • validate signale les cardinalités inattendues (many_to_many est un vrai warning).
  • indicator ajoute _merge avec left_only/right_only/both.
  • suffixes=("_order", "_cust") évite d’écraser des colonnes.

Join avec clés de noms différents

payments = pd.DataFrame({
    "cust_id": [100, 100, 103],
    "last_payment": ["2025-05-20", "2025-05-27", "2025-05-21"],
})
 
orders.merge(
    payments,
    left_on="customer_id",
    right_on="cust_id",
    how="left",
)

Joins basés sur l’index

customers_idx = customers.set_index("customer_id")
orders.join(customers_idx, on="customer_id", how="left")
  • .join est pratique quand la table droite a la clé en index.
  • Pour un multi-index, utilisez on=["level_0", "level_1"] ou alignez les index avant.

Gérer doublons et chevauchements

# Détecter les clés dupliquées avant le merge
dupes = customers["customer_id"].value_counts()
problem_keys = dupes[dupes > 1]
 
# Après merge, repérer les explosions
exploded = orders.merge(customers, on="customer_id", how="inner", validate="many_to_many")
  • Si le nombre de lignes monte alors qu’on attendait many_to_one, vérifier les doublons.
  • drop_duplicates(subset=keys) sur la table de dimensions aide souvent.

Fusionner plusieurs métriques d’un coup

agg = (
    orders.groupby("customer_id", as_index=False)
          .agg(total_amount=("amount", "sum"), orders_count=("order_id", "count"))
)
 
customers.merge(agg, on="customer_id", how="left")

Agrégation + merge réduit les chaînes de joins sur des données transactionnelles brutes.


Checklist de débogage

SymptômeVérification
Le nombre de lignes exploseInspecter _merge; régler validate sur la cardinalité attendue.
Lignes manquantes après mergeTester how="left" ou how="outer"; aligner les dtypes des clés.
Mauvaises correspondancesS’assurer que les clés ont le même dtype (str vs int, etc.).
Colonnes qui se chevauchentDéfinir suffixes pour éviter les écrasements.

Guides liés


Points clés

  • Choisir le type de join avec intention; left est le plus sûr pour enrichir.
  • validate, indicator et suffixes détectent tôt les problèmes.
  • Aligner clés et dtypes; dédupliquer les tables de dimensions pour éviter les explosions.