Skip to content

Pandas Merge & Join: Joins estilo SQL do jeito certo

Updated on

Em joins é comum errar: chaves desalinhadas duplicam linhas ou descartam registros. how="inner" é usado demais; validate e indicator quase nunca.

PAS:

  • Problema: Merges multiplicam linhas ou perdem dados por chaves erradas.
  • Agitar: Depurar leva tempo—sufixos duplicados, produtos cartesianos inesperados, linhas faltando.
  • Solução: Definir chaves explicitamente, escolher o how adequado, usar validate e indicator para auditar cedo.

Tabela rápida de joins

Tipo (how)Mantém esquerda?Mantém direita?Uso típico
inner✅ só matches✅ só matchesInterseção
left✅ tudo🚫 só matchesEnriquecer a esquerda
right🚫 só matches✅ tudoEnriquecer a direita (raro; normalmente inverta)
outer✅ tudo✅ tudoUnião completa com lacunas

Dados de exemplo

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 básico com chave de coluna

result = orders.merge(
    customers,
    on="customer_id",
    how="left",
    validate="many_to_one",  # tabela de dimensão esperada
    indicator=True,          # auditar cobertura
)
  • validate detecta cardinalidades inesperadas (many_to_many é alerta real).
  • indicator adiciona _merge com left_only/right_only/both.
  • suffixes=("_order", "_cust") evita sobrescrever colunas.

Join com nomes de chave diferentes

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 baseados em índice

customers_idx = customers.set_index("customer_id")
orders.join(customers_idx, on="customer_id", how="left")
  • .join é prático quando a tabela da direita já tem a chave no índice.
  • Em multi-índice, use on=["level_0", "level_1"] ou alinhe antes.

Tratar duplicados e sobreposições

# Encontrar duplicatas antes do merge
dupes = customers["customer_id"].value_counts()
problem_keys = dupes[dupes > 1]
 
# Detectar explosões após o merge
exploded = orders.merge(customers, on="customer_id", how="inner", validate="many_to_many")
  • Se a contagem de linhas sobe em um many_to_one esperado, investigue duplicados.
  • Considere drop_duplicates(subset=keys) na dimensão.

Mesclar várias métricas de uma vez

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

Agregue e depois una para evitar cadeias de merges em dados transacionais.


Checklist de depuração

SintomaChecar
Linhas explodiramVeja _merge; use validate conforme a cardinalidade esperada.
Linhas faltandoTeste how="left" ou how="outer"; alinhe dtypes das chaves.
Matches erradosAssegure dtypes iguais nas chaves (string vs int).
Colunas sobrepostasDefina suffixes para não sobrescrever.

Guias relacionados


Principais pontos

  • Escolha o tipo de join com intenção; para enriquecer, left é o mais seguro.
  • Use validate, indicator e suffixes para flagrar problemas cedo.
  • Alinhe chaves e dtypes; deduplique dimensões para evitar explosões.