Pandas Melt: Remodelar Dados Largos para o Formato Longo (Guia Completo)
Updated on
Você tem uma planilha em que cada mês é uma coluna separada — January, February, March, até December. Doze colunas de números de receita, e você precisa plotar uma série temporal, fazer um groupby, ou alimentar os dados em um modelo de machine learning. Nenhuma dessas operações funciona bem com dados em formato largo (wide). Você precisa de uma coluna para o nome do mês e outra coluna para o valor da receita. Essa transformação — transformar colunas em linhas — é exatamente o que pandas melt faz.
O problema piora rápido. Datasets largos com dezenas ou centenas de colunas são comuns em dados de pesquisa (survey), leituras de sensores, relatórios financeiros e exportações pivotadas do Excel ou SQL. Reestruturá-los manualmente é trabalhoso e propenso a erros. Cada coluna extra que você precisa despivotar significa mais código repetitivo se você tentar fazer isso sem a ferramenta certa.
A função pd.melt() resolve isso com uma única chamada. Ela pega um DataFrame largo e o “derrete” (melt) para o formato longo, transformando colunas selecionadas em linhas, preservando intactas suas colunas identificadoras. Este guia cobre a sintaxe completa, cada parâmetro, exemplos práticos de cenários do mundo real e comparações com funções relacionadas de remodelagem como pivot, stack e wide_to_long.
O que pd.melt() faz
pd.melt() despivota (unpivot) um DataFrame do formato largo (wide) para o formato longo (long). No formato largo, cada variável tem sua própria coluna. No formato longo (também chamado de formato “tidy”), existe uma coluna para nomes de variáveis e uma coluna para valores.
Aqui está a transformação conceitual:
Formato largo (antes do melt):
| student | math | science | english |
|---|---|---|---|
| Alice | 90 | 85 | 88 |
| Bob | 78 | 92 | 80 |
Formato longo (depois do melt):
| student | subject | score |
|---|---|---|
| Alice | math | 90 |
| Alice | science | 85 |
| Alice | english | 88 |
| Bob | math | 78 |
| Bob | science | 92 |
| Bob | english | 80 |
A coluna student é preservada como identificador, enquanto as três colunas de matéria (subject) são derretidas em duas colunas: uma contendo o nome da matéria e outra contendo a nota.
Sintaxe e parâmetros de pd.melt()
pd.melt(frame, id_vars=None, value_vars=None, var_name=None,
value_name='value', col_level=None, ignore_index=True)Você também pode chamá-la como um método no próprio DataFrame:
df.melt(id_vars=None, value_vars=None, var_name=None,
value_name='value', col_level=None, ignore_index=True)Referência de parâmetros
| Parâmetro | Descrição | Padrão |
|---|---|---|
frame | O DataFrame a ser derretido (não é necessário ao usar df.melt()) | Obrigatório |
id_vars | Coluna(s) a manter como variáveis identificadoras (não são derretidas) | None |
value_vars | Coluna(s) a despivotar em linhas. Se omitido, todas as colunas que não estão em id_vars serão usadas | None |
var_name | Nome da nova coluna que conterá os nomes das colunas originais | 'variable' |
value_name | Nome da nova coluna que conterá os valores | 'value' |
col_level | Se as colunas são um MultiIndex, o nível a derreter | None |
ignore_index | Se True, o resultado usa um novo índice inteiro. Se False, o índice original é mantido | True |
Exemplo básico: Notas de alunos
Comece com o exemplo de notas de alunos acima:
import pandas as pd
grades = pd.DataFrame({
'student': ['Alice', 'Bob', 'Charlie'],
'math': [90, 78, 85],
'science': [85, 92, 88],
'english': [88, 80, 91]
})
long = pd.melt(grades, id_vars=['student'], value_vars=['math', 'science', 'english'],
var_name='subject', value_name='score')
print(long)Saída:
student subject score
0 Alice math 90
1 Bob math 78
2 Charlie math 85
3 Alice science 85
4 Bob science 92
5 Charlie science 88
6 Alice english 88
7 Bob english 80
8 Charlie english 91Cada linha agora representa uma combinação aluno-matéria. O DataFrame original 3x4 (3 linhas, 4 colunas) vira um DataFrame 9x3 (9 linhas, 3 colunas).
Omitindo value_vars
Se você deixar value_vars de fora, o pandas derrete toda coluna que não está listada em id_vars:
long = grades.melt(id_vars=['student'], var_name='subject', value_name='score')
print(long)Isso produz o mesmo resultado do exemplo anterior. Omitir value_vars é conveniente quando você quer derreter todas as colunas não identificadoras.
Melting sem id_vars
Você também pode derreter sem especificar quaisquer colunas identificadoras. Isso coloca todas as colunas no par variável/valor:
temperatures = pd.DataFrame({
'Jan': [30, 28],
'Feb': [32, 31],
'Mar': [45, 42]
})
long = temperatures.melt(var_name='month', value_name='temp_f')
print(long)Saída:
month temp_f
0 Jan 30
1 Jan 28
2 Feb 32
3 Feb 31
4 Mar 45
5 Mar 42Isso é útil quando cada coluna é uma medição e não há identificador a preservar.
Múltiplas colunas identificadoras
Datasets reais frequentemente têm mais de um identificador. Você pode passar uma lista de nomes de colunas para id_vars:
sales = pd.DataFrame({
'region': ['North', 'South', 'North', 'South'],
'product': ['Widget', 'Widget', 'Gadget', 'Gadget'],
'q1_revenue': [1200, 1500, 800, 950],
'q2_revenue': [1400, 1600, 900, 1100],
'q3_revenue': [1100, 1450, 850, 1000],
'q4_revenue': [1500, 1700, 1000, 1200]
})
long_sales = sales.melt(
id_vars=['region', 'product'],
var_name='quarter',
value_name='revenue'
)
print(long_sales)Saída:
region product quarter revenue
0 North Widget q1_revenue 1200
1 South Widget q1_revenue 1500
2 North Gadget q1_revenue 800
3 South Gadget q1_revenue 950
4 North Widget q2_revenue 1400
5 South Widget q2_revenue 1600
6 North Gadget q2_revenue 900
7 South Gadget q2_revenue 1100
8 North Widget q3_revenue 1100
9 South Widget q3_revenue 1450
10 North Gadget q3_revenue 850
11 South Gadget q3_revenue 1000
12 North Widget q4_revenue 1500
13 South Widget q4_revenue 1700
14 North Gadget q4_revenue 1000
15 South Gadget q4_revenue 1200Tanto region quanto product são preservados em cada linha. As quatro colunas trimestrais são colapsadas em duas colunas.
Limpando após o melt
Após o melt, a coluna variable frequentemente contém strings que você quer limpar. No exemplo acima, a coluna de trimestre tem valores como q1_revenue em vez de apenas Q1. Use operações de string para corrigir isso:
long_sales['quarter'] = long_sales['quarter'].str.replace('_revenue', '').str.upper()
print(long_sales.head())Saída:
region product quarter revenue
0 North Widget Q1 1200
1 South Widget Q1 1500
2 North Gadget Q1 800
3 South Gadget Q1 950
4 North Widget Q2 1400Derretendo apenas colunas selecionadas
Às vezes você só quer derreter um subconjunto de colunas. Especifique-as explicitamente em value_vars:
survey = pd.DataFrame({
'respondent': ['R1', 'R2', 'R3'],
'age': [25, 34, 42],
'q1_satisfaction': [4, 5, 3],
'q2_satisfaction': [3, 4, 5],
'q3_satisfaction': [5, 3, 4],
'income': [50000, 75000, 60000]
})
# Only melt the satisfaction columns, keep age and income as identifiers
long_survey = survey.melt(
id_vars=['respondent', 'age', 'income'],
value_vars=['q1_satisfaction', 'q2_satisfaction', 'q3_satisfaction'],
var_name='question',
value_name='rating'
)
print(long_survey)Saída:
respondent age income question rating
0 R1 25 50000 q1_satisfaction 4
1 R2 34 75000 q1_satisfaction 5
2 R3 42 60000 q1_satisfaction 3
3 R1 25 50000 q2_satisfaction 3
4 R2 34 75000 q2_satisfaction 4
5 R3 42 60000 q2_satisfaction 5
6 R1 25 50000 q3_satisfaction 5
7 R2 34 75000 q3_satisfaction 3
8 R3 42 60000 q3_satisfaction 4A coluna income é mantida como identificador mesmo não fazendo parte das colunas derretidas.
Exemplo do mundo real: Dados de série temporal
Dados financeiros e econômicos frequentemente chegam em formato largo com datas como cabeçalhos de coluna. O melt converte isso em uma série temporal pronta para plotar:
import pandas as pd
gdp = pd.DataFrame({
'country': ['USA', 'UK', 'Germany'],
'2020': [20.94, 2.71, 3.89],
'2021': [23.00, 3.12, 4.26],
'2022': [25.46, 3.07, 4.07],
'2023': [27.36, 3.33, 4.46]
})
gdp_long = gdp.melt(id_vars=['country'], var_name='year', value_name='gdp_trillion_usd')
gdp_long['year'] = gdp_long['year'].astype(int)
gdp_long = gdp_long.sort_values(['country', 'year']).reset_index(drop=True)
print(gdp_long)Saída:
country year gdp_trillion_usd
0 Germany 2020 3.89
1 Germany 2021 4.26
2 Germany 2022 4.07
3 Germany 2023 4.46
4 UK 2020 2.71
5 UK 2021 3.12
6 UK 2022 3.07
7 UK 2023 3.33
8 USA 2020 20.94
9 USA 2021 23.00
10 USA 2022 25.46
11 USA 2023 27.36Agora você pode facilmente plotar o PIB ao longo do tempo, agrupar por país ou calcular crescimento ano a ano.
Melting com colunas MultiIndex
Se seu DataFrame tem cabeçalhos de coluna em múltiplos níveis, use o parâmetro col_level para especificar qual nível derreter:
arrays = [['score', 'score', 'attendance', 'attendance'],
['midterm', 'final', 'midterm', 'final']]
columns = pd.MultiIndex.from_arrays(arrays, names=['metric', 'exam'])
data = pd.DataFrame([[85, 90, 95, 100], [78, 82, 90, 88]],
index=['Alice', 'Bob'], columns=columns)
# Melt the top level
melted = data.melt(col_level=0, var_name='metric', value_name='value', ignore_index=False)
print(melted)Para cenários multi-nível complexos, pode ser necessário achatar (flatten) as colunas primeiro usando droplevel() ou juntando níveis com um underscore antes de derreter.
Melt vs Pivot: Operações inversas
melt() e pivot() são operações inversas. Melt converte de largo para longo. Pivot converte de longo para largo.
import pandas as pd
# Start wide
wide = pd.DataFrame({
'name': ['Alice', 'Bob'],
'math': [90, 78],
'science': [85, 92]
})
# Melt: wide -> long
long = wide.melt(id_vars='name', var_name='subject', value_name='score')
print("Long format:")
print(long)
# Pivot: long -> wide (round-trip)
back_to_wide = long.pivot(index='name', columns='subject', values='score').reset_index()
back_to_wide.columns.name = None
print("\nBack to wide format:")
print(back_to_wide)Saída:
Long format:
name subject score
0 Alice math 90
1 Bob math 78
2 Alice science 85
3 Bob science 92
Back to wide format:
name math science
0 Alice 90 85
1 Bob 78 92Diferença-chave: pivot() exige combinações únicas de índice-coluna. Se seus dados longos têm duplicatas, use pivot_table() com uma função de agregação.
Melt vs Stack vs wide_to_long
O pandas fornece várias funções para remodelagem. Aqui vai quando usar cada uma:
| Função | Direção | Melhor para | Diferença-chave |
|---|---|---|---|
melt() | largo para longo | Despivotar colunas específicas em linhas | Baseado em colunas; mais intuitivo para iniciantes |
stack() | largo para longo | Colapsar níveis de colunas em níveis de índice | Baseado em índice; funciona com MultiIndex |
wide_to_long() | largo para longo | Colunas com prefixo comum e sufixo numérico (ex.: score1, score2) | Faz parsing automático dos stub names |
pivot() | longo para largo | Espalhar valores em colunas (chaves únicas) | Inverso de melt() |
unstack() | longo para largo | Expandir níveis do índice em colunas | Inverso de stack() |
Quando usar stack() em vez disso
stack() opera no índice de colunas e o empurra para o índice de linhas. É mais útil quando você já está trabalhando com um MultiIndex e quer remodelar no nível de índice:
wide = pd.DataFrame({
'math': [90, 78],
'science': [85, 92]
}, index=['Alice', 'Bob'])
stacked = wide.stack()
print(stacked)Saída:
Alice math 90
science 85
Bob math 78
science 92
dtype: int64O resultado é uma Series com MultiIndex, não um DataFrame com colunas nomeadas como melt() produz. Use melt() quando você quiser uma saída limpa em DataFrame com colunas explicitamente nomeadas.
Quando usar wide_to_long()
wide_to_long() é projetado para colunas que seguem um padrão de nome como score1, score2, score3:
df = pd.DataFrame({
'student': ['Alice', 'Bob'],
'score1': [90, 78],
'score2': [85, 92],
'score3': [88, 80]
})
long = pd.wide_to_long(df, stubnames='score', i='student', j='exam_num')
print(long.reset_index())Saída:
student exam_num score
0 Alice 1 90
1 Alice 2 85
2 Alice 3 88
3 Bob 1 78
4 Bob 2 92
5 Bob 3 80Use wide_to_long() quando suas colunas têm um padrão consistente de prefixo-sufixo. Caso contrário, melt() é mais flexível.
Considerações de performance
Para a maioria dos datasets (abaixo de alguns milhões de linhas), melt() é rápido o suficiente. Aqui estão benchmarks em um DataFrame com 100.000 linhas e 50 colunas sendo derretidas:
| Operação | Tempo aproximado |
|---|---|
melt() com 50 colunas de valor | ~15 ms |
equivalente com stack() | ~10 ms |
loop manual com concat() | ~500 ms |
Dicas para melhor performance:
- Especifique
value_varsexplicitamente — derreter apenas as colunas necessárias é mais rápido do que derreter todas. - Use
ignore_index=True(padrão) — preservar o índice original adiciona overhead. - Evite derreter e imediatamente repivotar — se você precisa de outro formato largo, considere usar
pivot_table()ourename()diretamente em vez de fazer um “vai e volta”. - Para DataFrames muito grandes (100M+ linhas após o melt), considere usar polars ou Dask, que oferecem lazy evaluation e processamento paralelo.
# Only melt the columns you actually need
long = df.melt(
id_vars=['id'],
value_vars=['col_a', 'col_b', 'col_c'], # Not all 50 columns
var_name='metric',
value_name='reading'
)Erros comuns e como corrigir
1. KeyError: Coluna não encontrada
Isso acontece quando um nome de coluna em id_vars ou value_vars não existe no DataFrame:
# Wrong: column name has a typo
long = df.melt(id_vars=['stduent']) # KeyError
# Fix: check column names first
print(df.columns.tolist())2. Linhas duplicadas que você não esperava
O melt em si não cria linhas duplicadas — ele cria uma linha por combinação de variável-identificadora. Se você vê duplicatas, significa que seus dados originais tinham linhas identificadoras duplicadas:
# Check for duplicates in your id columns
print(df.duplicated(subset=['student']).sum())3. Tipos de dados mistos na coluna de valor
Quando você derrete colunas com dtypes diferentes (por exemplo, algumas int64 e outras float64), o pandas promove (upcast) a coluna de valor para o tipo mais geral. Se você derrete uma mistura de colunas numéricas e de texto, a coluna de valor vira dtype object:
df = pd.DataFrame({
'id': [1, 2],
'score': [90, 85],
'grade': ['A', 'B']
})
long = df.melt(id_vars='id')
print(long.dtypes)
# variable object
# value object <-- both score and grade become objectPara evitar isso, derreta colunas numéricas e colunas de texto separadamente.
Visualize dados derretidos com PyGWalker
Após remodelar seus dados do formato largo para o formato longo, o próximo passo natural é explorar o resultado visualmente — verificar distribuições, comparar grupos ou identificar outliers. PyGWalker (opens in a new tab) é uma biblioteca Python open-source que transforma qualquer DataFrame do pandas em uma interface interativa de exploração visual estilo Tableau dentro do Jupyter Notebook.
import pandas as pd
import pygwalker as pyg
# Melt your wide data into long format
grades = pd.DataFrame({
'student': ['Alice', 'Bob', 'Charlie', 'Diana'],
'math': [90, 78, 85, 92],
'science': [85, 92, 88, 79],
'english': [88, 80, 91, 84]
})
long = grades.melt(id_vars='student', var_name='subject', value_name='score')
# Launch interactive visualization
walker = pyg.walk(long)Com o PyGWalker, você pode arrastar subject para o eixo x e score para o eixo y, e então colorir por student para comparar instantaneamente o desempenho entre matérias — sem precisar escrever código de gráfico. Ele suporta gráficos de barras, scatter plots, box plots e mais, tudo por drag-and-drop.
Experimente o PyGWalker no Google Colab (opens in a new tab), Kaggle (opens in a new tab), ou instale com
pip install pygwalker.
FAQ
O que pandas melt faz?
O melt() do pandas remodela um DataFrame do formato largo para o formato longo. Ele pega colunas e as transforma em linhas, criando duas novas colunas: uma para os nomes das colunas originais (variable) e outra para os valores. Isso também é conhecido como “unpivoting” (despivotar).
Qual é a diferença entre melt e pivot no pandas?
melt() converte do formato largo para o formato longo (colunas viram linhas). pivot() faz o oposto — converte do formato longo para o formato largo (linhas viram colunas). Eles são operações inversas. Se você derreter um DataFrame e depois fizer pivot no resultado usando os mesmos parâmetros, você volta ao DataFrame original.
Quando devo usar melt vs stack no pandas?
Use melt() quando você quer um DataFrame limpo com colunas nomeadas e controle explícito sobre quais colunas despivotar. Use stack() quando você está trabalhando com colunas MultiIndex e quer empurrar níveis de coluna para o índice de linhas. melt() é mais intuitivo para iniciantes; stack() é mais poderoso para remodelagem hierárquica.
Como derreto múltiplas colunas no pandas?
Passe uma lista de nomes de colunas para o parâmetro value_vars: df.melt(id_vars=['id'], value_vars=['col_a', 'col_b', 'col_c']). Todas as colunas listadas serão despivotadas em linhas. Se você omitir value_vars, o pandas derrete todas as colunas não listadas em id_vars.
Posso derreter um DataFrame com nomes de colunas duplicados?
O pandas vai derreter o DataFrame, mas o resultado pode ser confuso porque a coluna variable terá valores duplicados. Renomeie as colunas duplicadas primeiro usando df.columns = [...] ou df.rename() para evitar ambiguidade.
Como reverto uma operação de melt no pandas?
Use pivot() ou pivot_table() para converter os dados derretidos (longos) de volta para o formato largo: long.pivot(index='id', columns='variable', values='value'). Use pivot_table() se houver combinações duplicadas de índice-coluna que exijam agregação.
Conclusão
A função melt() do pandas é a forma padrão de converter DataFrames em formato largo para o formato longo (tidy) em Python. Principais pontos:
- Use
id_varspara especificar quais colunas manter como identificadores. - Use
value_varspara controlar quais colunas serão derretidas. Omita para derreter tudo, exceto os identificadores. - Use
var_nameevalue_namepara dar nomes significativos às colunas de saída. - Melt e pivot são inversos — use
melt()para ir de largo→longo epivot()para ir de longo→largo. - Escolha
melt()em vez destack()quando você quer um DataFrame plano com nomes de coluna explícitos em vez de uma Series com MultiIndex. - Limpe após o melt — use métodos de string na coluna de variável para remover prefixos, sufixos ou reformatar valores.
Depois de remodelar seus dados, ferramentas como PyGWalker (opens in a new tab) permitem explorar visualmente o resultado sem escrever código de gráfico, tornando o fluxo de trabalho de análise mais rápido e intuitivo.