Pandas Pivot vs Melt: Como remodelar dados do jeito certo
Updated on
Remodelar dados costuma ser o gargalo antes de analisar ou visualizar. Escolhas erradas duplicam linhas, perdem dados ou criam tabelas largas difíceis de usar.
PAS:
- Problema: Dados wide/long bagunçados atrasam gráficos e agregações.
- Agitar:
pivotcom duplicados gera erro;meltmal usado multiplica linhas ou perde identificadores. - Solução: Fluxo tidy—
pivot_tablequando há duplicados,pivotcom chaves únicas,meltpara ir a long,stack/unstackpara ajustar MultiIndex.
Guia rápido
| Método | Direção | Quando usar | Lida com duplicados? |
|---|---|---|---|
pivot | long → wide | Chaves únicas | 🚫 (falha com duplicados) |
pivot_table | long → wide | Precisa agregar ou há duplicados | ✅ via aggfunc |
melt | wide → long | Normalizar colunas em linhas | N/A |
stack / unstack | wide ↔ long em níveis de índice | MultiIndex | N/A |
Dados de exemplo
import pandas as pd
sales = pd.DataFrame({
"region": ["NA", "NA", "EU", "EU"],
"quarter": ["Q1", "Q2", "Q1", "Q2"],
"product": ["A", "A", "A", "A"],
"revenue": [120, 140, 110, 150],
"units": [10, 11, 9, 12],
})Formato wide com pivot
wide = sales.pivot(index="region", columns="quarter", values="revenue")- Requer combinações únicas de
region+quarter. - Use
.reset_index()para achatar se precisar.
Wide com agregação (pivot_table)
table = sales.pivot_table(
index="region",
columns="quarter",
values="revenue",
aggfunc="sum",
margins=True,
margins_name="Total"
)- Lida com duplicados agregando.
fill_value=0deixa o export limpo.
Vários valores e agregações
multi = sales.pivot_table(
index="region",
columns="quarter",
values=["revenue", "units"],
aggfunc={"revenue": "sum", "units": "mean"},
)Achatar colunas:
multi.columns = [f"{metric}_{col}" for metric, col in multi.columns]
multi = multi.reset_index()Formato long com melt
long = sales.melt(
id_vars=["region", "quarter"],
value_vars=["revenue", "units"],
var_name="metric",
value_name="value",
)- Ideal para libs que esperam tidy data (uma variável por coluna, uma observação por linha).
- Controle as colunas a desfazer com
value_vars.
Stack e unstack para MultiIndex
stacked = table.stack()
unstacked = stacked.unstack()- Reorganiza níveis sem redefinir chaves.
- Selecione o nível com
stack(level="quarter")ouunstack(level=-1).
Armadilhas comuns
| Problema | Solução |
|---|---|
ValueError: Index contains duplicate entries com pivot | Use pivot_table com agregação. |
| Ordem de colunas inesperada | Ordene: table = table.reindex(sorted(table.columns), axis=1). |
| MultiIndex pouco legível | Achate após pivot_table. |
| Valores faltando após reshape | fill_value ou stack(dropna=False) para manter vazios. |
Dicas de fluxo
- Normalize primeiro:
melt→groupby/agg→pivot_tablepara apresentação. - Para gráficos, mantenha os dados long; wide é melhor para relatórios/exports.
- Depois de
pivot_table, exporte:table.to_excel("report.xlsx").
Guias relacionados
Em resumo
pivotcom chaves únicas,pivot_tablequando precisa agregar,meltpara ir a long.- Achate MultiIndex após pivots complexos para exportar limpo.
- Combine reshape com
groupbypara gerar rápido dados prontos para análise.