Skip to content

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

studentmathscienceenglish
Alice908588
Bob789280

Formato longo (depois do melt):

studentsubjectscore
Alicemath90
Alicescience85
Aliceenglish88
Bobmath78
Bobscience92
Bobenglish80

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âmetroDescriçãoPadrão
frameO DataFrame a ser derretido (não é necessário ao usar df.melt())Obrigatório
id_varsColuna(s) a manter como variáveis identificadoras (não são derretidas)None
value_varsColuna(s) a despivotar em linhas. Se omitido, todas as colunas que não estão em id_vars serão usadasNone
var_nameNome da nova coluna que conterá os nomes das colunas originais'variable'
value_nameNome da nova coluna que conterá os valores'value'
col_levelSe as colunas são um MultiIndex, o nível a derreterNone
ignore_indexSe True, o resultado usa um novo índice inteiro. Se False, o índice original é mantidoTrue

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     91

Cada 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      42

Isso é ú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     1200

Tanto 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     1400

Derretendo 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       4

A 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.36

Agora 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       92

Diferenç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çãoDireçãoMelhor paraDiferença-chave
melt()largo para longoDespivotar colunas específicas em linhasBaseado em colunas; mais intuitivo para iniciantes
stack()largo para longoColapsar níveis de colunas em níveis de índiceBaseado em índice; funciona com MultiIndex
wide_to_long()largo para longoColunas com prefixo comum e sufixo numérico (ex.: score1, score2)Faz parsing automático dos stub names
pivot()longo para largoEspalhar valores em colunas (chaves únicas)Inverso de melt()
unstack()longo para largoExpandir níveis do índice em colunasInverso 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: int64

O 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     80

Use 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çãoTempo aproximado
melt() com 50 colunas de valor~15 ms
equivalente com stack()~10 ms
loop manual com concat()~500 ms

Dicas para melhor performance:

  1. Especifique value_vars explicitamente — derreter apenas as colunas necessárias é mais rápido do que derreter todas.
  2. Use ignore_index=True (padrão) — preservar o índice original adiciona overhead.
  3. Evite derreter e imediatamente repivotar — se você precisa de outro formato largo, considere usar pivot_table() ou rename() diretamente em vez de fazer um “vai e volta”.
  4. 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 object

Para 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_vars para especificar quais colunas manter como identificadores.
  • Use value_vars para controlar quais colunas serão derretidas. Omita para derreter tudo, exceto os identificadores.
  • Use var_name e value_name para dar nomes significativos às colunas de saída.
  • Melt e pivot são inversos — use melt() para ir de largo→longo e pivot() para ir de longo→largo.
  • Escolha melt() em vez de stack() 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.

📚