Pandas: Concatenação e Anexação
Última atualização: 2026-08-26
mesclagem realiza "junção horizontal" (correspondência de colunas por chave), enquanto concat realiza "concatenação vertical/horizontal" (empilhamento de linhas ou colunas). Combinar 12 meses de dados de vendas em uma única tabela anual, ou mesclar relatórios de 3 filiais em um relatório principal — é para isso que o concat serve. Esta seção cobre a direção do eixo do concat, indexação, alinhamento e chaves para rótulos multinível, além de estratégias para escolher entre concat e mesclagem.
1. What You Will Learn
- ❶ concat axis-based concatenation
- ❷ axis=0 vs axis=1
- ❸ ignore_index for rebuilding the index
- ❹ keys for multi-level labels
- ❺ join alignment strategies
2. Concatenação de Dados de 12 Meses de Charlie
(1) Ponto de Dificuldade: Ler 12 CSVs Um por Um
Charlie tem 12 CSVs de vendas mensais, e uni-los manualmente é trabalhoso:
import pandas as pd
# Imagine 12 DataFrames separados
jan = pd.DataFrame({'date': ['2024-01-15'], 'sales': [5000]})
feb = pd.DataFrame({'date': ['2024-02-20'], 'sales': [4500]})
mar = pd.DataFrame({'date': ['2024-03-10'], 'sales': [5200]})
# ... mais 9 meses
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado — por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
(2) Solução: Concatenar de Uma Só Vez com concat
▶ Exemplo: Concatenação Vertical com concat (Dificuldade ⭐)
import pandas as pd
jan = pd.DataFrame({'date': ['2024-01-15'], 'sales': [5000]})
feb = pd.DataFrame({'date': ['2024-02-20'], 'sales': [4500]})
mar = pd.DataFrame({'date': ['2024-03-10'], 'sales': [5200]})
# Empilhe verticalmente (axis=0 é o padrão)
year = pd.concat([jan, feb, mar], ignore_index=True)
print(year)
# date sales
# 0 2024-01-15 5000
# 1 2024-02-20 4500
# 2 2024-03-10 5200
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado — por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
3. Parâmetros Básicos do concat
(1) Vertical vs Horizontal
▶ Exemplo
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado — por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
: axis=0 vs axis=1 (Dificuldade ⭐)
import pandas as pd
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})
# axis=0: empilhar linhas (vertical)
print("axis=0 (vertical):")
print(pd.concat([df1, df2], axis=0))
# A B
# 0 1 3
# 1 2 4
# 0 5 7 ← índice se repete!
# 1 6 8
# axis=1: empilhar colunas (horizontal)
print("\naxis=1 (horizontal):")
print(pd.concat([df1, df2], axis=1))
# A B A B
# 0 1 3 5 7
# 1 2 4 6 8
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado — por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
(2) Reconstruindo o Índice com ignore_index
▶ Exemplo
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado — por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
: Reconstruindo o índice com ignore_index (Dificuldade ⭐)
import pandas as pd
df1 = pd.DataFrame({'A': [1, 2]})
df2 = pd.DataFrame({'A': [3, 4]})
df3 = pd.DataFrame({'A': [5, 6]})
# Sem ignore_index — índices originais preservados (podem ter lacunas)
result1 = pd.concat([df1, df2, df3])
print(result1.index.tolist()) # [0, 1, 0, 1, 0, 1] — duplicado!
# Com ignore_index — índice sequencial limpo
result2 = pd.concat([df1, df2, df3], ignore_index=True)
print(result2.index.tolist()) # [0, 1, 2, 3, 4, 5] — limpo!
print(result2)
# A
# 0 1
# 1 2
# 2 3
# 3 4
# 4 5
# 5 6
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem o pandas pré-instalado — por favor, instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
4. Etiquetas Multinível com chaves
(1) Rotulando Fontes de Dados
▶ Exemplo
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado — por favor, instale localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
: Rotulando fontes com chaves (Dificuldade ⭐⭐)
import pandas as pd
q1 = pd.DataFrame({'sales': [100, 200, 300]})
q2 = pd.DataFrame({'sales': [150, 250, 350]})
q3 = pd.DataFrame({'sales': [180, 280, 380]})
# keys creates MultiIndex — trace which DataFrame each row came from
result = pd.concat([q1, q2, q3], keys=['Q1', 'Q2', 'Q3'])
print(result)
# sales
# Q1 0 100
# 1 200
# 2 300
# Q2 0 150
# 1 250
# 2 350
# Q3 0 180
# 1 280
# 2 380
# Select by key
print(result.loc['Q2'])
# sales
# 0 150
# 1 250
# 2 350
# Add source column instead of MultiIndex
result2 = pd.concat([q1, q2, q3], keys=['Q1', 'Q2', 'Q3'], names=['quarter'])
result2 = result2.reset_index(level=0)
print(result2)
# quarter sales
# 0 Q1 100
# 1 Q1 200
# ...
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado — por favor, instale localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
5. Estratégias de Alinhamento em Join
(1) Quando os Nomes das Colunas Não Correspondem Totalmente
▶ Exemplo
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado — por favor, instale localmente (`pip install pandas`) e siga alongamente. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
: join='outer' vs 'inner' (Dificuldade ⭐⭐)
import pandas as pd
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4], 'C': [5, 6]})
df2 = pd.DataFrame({'B': [7, 8], 'C': [9, 10], 'D': [11, 12]})
# join='outer' (padrão) — mantém todas as colunas, preenche com NaN
print("outer:")
print(pd.concat([df1, df2], axis=0, join='outer'))
# A B C D
# 0 1.0 3 5 NaN
# 1 2.0 4 6 NaN
# 0 NaN 7 9 11.0
# 1 NaN 8 10 12.0
# join='inner' — apenas colunas compartilhadas
print("\ninner:")
print(pd.concat([df1, df2], axis=0, join='inner'))
# B C
# 0 3 5
# 1 4 6
# 0 7 9
# 1 8 10
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado — por favor, instale localmente (`pip install pandas`) e siga alongamente. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
6. concat vs mesclagem
| Característica | concat | mesclagem |
|---|---|---|
| Operação | Empilhamento (vertical/horizontal) | Junção (correspondência por chave) |
| Chave | Não requerida | Requerida em on/left_on |
| Contagem de linhas | Soma das linhas da fonte (axis=0) | ≤ soma das linhas da fonte |
| Contagem de colunas | Soma das colunas da fonte (axis=1) | União das colunas da fonte |
| Caso de uso | Empilhar dados com estrutura idêntica | Juntar dados com estruturas diferentes |
| Cenário típico | 12 meses unidos em uma tabela anual | Usuários + pedidos unidos juntos |
▶ Exemplo
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado — por favor, instale localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
: Quando usar concat vs mesclagem (Dificuldade ⭐⭐)
import pandas as pd
# Use CONCAT: mesma estrutura, empilhe verticalmente
jan_sales = pd.DataFrame({'product': ['A', 'B'], 'sales': [100, 200]})
feb_sales = pd.DataFrame({'product': ['A', 'B'], 'sales': [150, 250]})
annual = pd.concat([jan_sales, feb_sales], keys=['Jan', 'Feb'])
# Use MERGE: estruturas diferentes, vincule por chave
products = pd.DataFrame({'product': ['A', 'B'], 'price': [10, 20]})
categories = pd.DataFrame({'product': ['A', 'B'], 'category': ['Electronics', 'Home']})
enriched = pd.merge(products, categories, on='product')
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado — por favor, instale localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
7. Exemplo Completo: Concatenação e Análise de Dados Multi-Fonte
(5) ▶ Tipos de Concatenação do concat
graph TB
A[Multiple DataFrames] --> B{Direção da concatenação?}
B -->|Eixo vertical=0| C[Empilhar linhas de cima para baixo]
B -->|Eixo horizontal=1| D[Colocar colunas lado a lado]
C --> E{Nomes das colunas coincidem?}
E -->|Sim| F[Concatenação perfeita]
E -->|Não| G[join='outer' preenche NaN / join='inner' mantém interseção]
D --> H{Índices das linhas coincidem?}
H -->|Sim| I[Concatenação alinhada]
H -->|Não| J[Preenchimento cruzado com NaN]
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado — instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
▶ Exemplo
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado — instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
: Fluxo de trabalho completo de concatenação multi-fonte (Dificuldade ⭐⭐⭐)
import pandas as pd
import numpy as np
# ============================================
# Exemplo abrangente: concat multi-fonte
# 3 relatórios regionais → análise anual
# ============================================
# 1. Relatórios mensais regionais
np.random.seed(42)
regions = {
'Norte': pd.DataFrame({
'month': pd.date_range('2024-01', periods=6, freq='MS'),
'sales': np.random.randint(3000, 8000, 6),
'orders': np.random.randint(50, 150, 6)
}),
'Sul': pd.DataFrame({
'month': pd.date_range('2024-01', periods=6, freq='MS'),
'sales': np.random.randint(2000, 6000, 6),
'orders': np.random.randint(30, 120, 6)
}),
'Leste': pd.DataFrame({
'month': pd.date_range('2024-01', periods=6, freq='MS'),
'sales': np.random.randint(1500, 5000, 6),
'orders': np.random.randint(20, 100, 6)
})
}
# 2. Concatenar com chaves para marcar a região
all_data = pd.concat(regions, names=['region', 'idx'])
all_data = all_data.reset_index(level=0).reset_index(drop=True)
print(f"Total de linhas: {len(all_data)}")
# 3. Adicionar colunas derivadas
all_data['avg_order_value'] = (all_data['sales'] / all_data['orders']).round(2)
# 4. Analisar por região
region_summary = all_data.groupby('region').agg(
total_sales=('sales', 'sum'),
total_orders=('orders', 'sum'),
avg_monthly_sales=('sales', 'mean')
).round(0)
print("\n=== Resumo Regional ===")
print(region_summary)
# 5. Tendência mensal em todas as regiões
monthly = all_data.groupby('month')['sales'].sum()
print(f"\nMês de pico: {monthly.idxmax().strftime('%Y-%m')}")
> **Saída:** Execute isso em um ambiente Python local (pandas 2.x). O servidor Piston não tem pandas pré-instalado — instale-o localmente (`pip install pandas`) e acompanhe. Os valores reais podem variar ligeiramente dependendo da sua versão do pandas.
❓ Perguntas Frequentes
Q: Qual é a diferença entre concat e mesclagem? R: concat empilha dados — ele concatena linhas verticalmente ou colunas horizontalmente sem exigir uma chave correspondente. mesclagem une dados — ele combina linhas de duas tabelas por chave, semelhante a um JOIN do SQL. Várias tabelas com a mesma estrutura fundidas em uma → concat. Tabelas com estruturas diferentes vinculadas por uma coluna → mesclagem. Regra prática: "Estrutura igual? Empilhe com concat. Estrutura diferente? Junte com mesclagem."
Q: O que fazem axis=0 e axis=1? R: axis=0 (padrão) concatena linhas verticalmente — empilhando de cima para baixo, aumentando a contagem de linhas. axis=1 concatena colunas horizontalmente — colocando lado a lado, aumentando a contagem de colunas. A concatenação vertical alinha automaticamente as colunas (as que faltam são preenchidas com NaN); a concatenação horizontal alinha automaticamente as linhas (as que faltam são preenchidas com NaN).
Q: Quando devo usar ignore_index? R: Para concatenação vertical, quase sempre você quer ignore_index=True — ele reconstrói um índice sequencial e evita índices duplicados ([0,1,0,1,0,1]). Mantenha o índice original apenas se ele carregar significado (por exemplo, um índice de data). A concatenação horizontal não precisa de ignore_index (o alinhamento das linhas depende do índice).
Q: Por que o append foi descontinuado? R: df.append() foi marcado como descontinuado no Pandas 1.4 e totalmente removido na versão 2.0. Motivo: append cria um novo objeto a cada chamada, resultando em desempenho O(n²) em um laço; pd.concat concatena tudo em uma única passagem em O(n). Substituição:
pd.concat([df1, df2]). Para adições baseadas em laço: colete em uma lista primeiro, depois faça o concat uma vez no final.
Q: E se os nomes das colunas forem diferentes? R: Durante a concatenação vertical, nomes de colunas incompatíveis produzem NaN — apenas colunas com o mesmo nome têm seus dados combinados. Soluções: ① renomeie as colunas antes da concatenação para unificar os nomes; ② use join='inner' para manter apenas as colunas compartilhadas; ③ lide manualmente com as colunas NaN após a concatenação. Melhor prática: unifique os nomes das colunas antes de chamar o concat.
Q: Como otimizar o desempenho do concat? R: Evite chamar o concat repetidamente dentro de um laço — cada chamada cria um novo DataFrame. A abordagem correta: colete todos os DataFrames em uma lista, depois faça o concat uma vez.
frames = [df1, df2, ..., df100]; result = pd.concat(frames). Isso faz a diferença entre O(n) e O(n²) em comparação com adições baseadas em laço.
Q: O que faz o verify_integrity? R: verify_integrity=True verifica se o índice concatenado contém duplicatas e levanta um ValueError se tiver. Use-o para garantir a integridade dos dados — por exemplo, IDs únicos nunca devem aparecer duas vezes. No entanto, a verificação tem um custo de desempenho, então pule-a para grandes conjuntos de dados. Para uso no dia a dia, ignore_index=True é mais simples.
📖 Resumo
- concat empilha dados (concatenação vertical de linhas / concatenação horizontal de colunas) sem necessidade de uma chave correspondente
- axis=0 concatena linhas verticalmente (padrão), axis=1 concatena colunas horizontalmente
- ignore_index=True reconstrói um índice sequencial — quase sempre necessário para concatenação vertical
- keys marca fontes de dados, produzindo um MultiIndex que rastreia a fonte de cada linha
- join='outer' mantém todas as colunas (preenchendo com NaN), join='inner' mantém apenas colunas compartilhadas
- concat vs mesclagem: use concat para empilhar estruturas idênticas, use mesclagem para unir estruturas diferentes
- Evite concat em um laço — colete em uma lista primeiro, depois use concat uma única vez
📝 Exercícios
- Básico (Dificuldade ⭐): Crie 3 DataFrames com estrutura idêntica (dados de vendas Q1/Q2/Q3), concatene-os verticalmente com concat (ignore_index=True) e calcule o total de vendas.
- Intermediário (Dificuldade ⭐⭐): Crie 2 DataFrames com nomes de colunas parcialmente diferentes, concatene-os com join='outer' e join='inner' respectivamente, e compare as diferenças nas colunas.
- Desafio (Dificuldade ⭐⭐⭐): Simule 6 meses de dados para 4 regiões, concatene com concat(keys=regions) → limpe com reset_index → compute totais por região → examine as tendências mensais.