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.

⚠️ Nota: O código abaixo requer um ambiente Python local para ser executado.

1. What You Will Learn


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:

PYTHON
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
TEXT 📖 Somente leitura
> **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 ⭐)

PYTHON
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
TEXT 📖 Somente leitura
> **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

TEXT 📖 Somente leitura
> **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 ⭐)

PYTHON
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
TEXT 📖 Somente leitura
> **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

TEXT 📖 Somente leitura
> **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 ⭐)

PYTHON
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
TEXT 📖 Somente leitura
> **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

TEXT 📖 Somente leitura
> **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 ⭐⭐)

PYTHON
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
# ...
TEXT 📖 Somente leitura
> **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

TEXT 📖 Somente leitura
> **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 ⭐⭐)

PYTHON
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
TEXT 📖 Somente leitura
> **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

TEXT 📖 Somente leitura
> **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 ⭐⭐)

PYTHON
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')
TEXT 📖 Somente leitura
> **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

100%
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]
TEXT 📖 Somente leitura
> **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

TEXT 📖 Somente leitura
> **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 ⭐⭐⭐)

PYTHON
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')}")
TEXT 📖 Somente leitura
> **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


📝 Exercícios

  1. 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.
  2. 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.
  3. 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.

← Previous: Merge and Join · Next: Reshaping and Pivoting →

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%