Reestruturar com pivot, melt e stack
Converter tabelas longas e largas e reconhecer quando a chave exige agregação.
A mesma informação pode ocupar tabelas com formas diferentes. No formato longo, uma variável identifica o produto e outra guarda a quantidade. No formato largo, cada produto pode ser uma coluna. Reestruturar muda a disposição, mantendo os valores quando a correspondência é única.
Longo para largo com pivot
import pandas as pd
longa = pd.DataFrame({
"cidade": ["Porto", "Porto", "Braga", "Braga"],
"produto": ["pão", "leite", "pão", "leite"],
"quantidade": [2, 3, 5, 1],
})
larga = longa.pivot(index="cidade", columns="produto", values="quantidade")
print(larga.to_string())
reconstruida = larga.reset_index().melt(id_vars="cidade", var_name="produto", value_name="quantidade")
print(reconstruida.sort_values(["cidade", "produto"]).to_string(index=False))Dados de entrada
A linha Porto passa a ter leite 3 e pão 2; a linha Braga tem leite 1 e pão 5. index escolhe os identificadores das linhas; columns os valores que se tornam nomes de colunas; values a medida que preenche cada célula.
Para pivot, cada par cidade-produto precisa de um único valor. Se houver duas vendas de pão no Porto, a posição correspondente tem dois candidatos e pandas lança um erro. A tabela precisa primeiro de uma decisão: somar as vendas, calcular a média ou conservar outra dimensão que as distinga.
Largo para longo com melt
melt conserva as colunas id_vars e transforma as restantes em pares variável-valor. var_name dá nome à coluna que guarda o nome antigo da medida. value_name dá nome à coluna que guarda o valor.
Se a tabela tem datas e quantidades por produto:
longa = larga.melt(
id_vars="data",
value_vars=["pão", "leite"],
var_name="produto",
value_name="quantidade",
)
Cada linha inicial origina duas linhas, uma por produto. Não duplicámos observações da mesma medida; passámos a identificar a medida numa coluna. Conserva todos os identificadores necessários para voltar à forma original.
stack e unstack
stack move um nível dos nomes de colunas para o índice de linhas. unstack move um nível do índice para as colunas. Isto produz ou usa um MultiIndex, um índice com vários níveis.
serie = longa.set_index(["cidade", "produto"])["quantidade"]
larga = serie.unstack("produto")
Agora o par cidade-produto identifica cada valor da Series. Ao deslocar produto para as colunas, cidade fica nas linhas. A ordenação e a preservação de valores em falta de stack mudaram entre versões; se o enunciado exigir uma forma exata, confere os argumentos da versão usada nas aulas.
O que não é uma reestruturação
df.T troca linhas por colunas, mas não resolve uma chave duplicada nem calcula totais. rename muda nomes sem mudar a disposição. merge associa observações entre tabelas. pivot_table, na página seguinte, pode agregar vários valores na mesma célula.
Antes de escolher a operação, escreve que colunas identificam uma observação e qual é a medida. Depois confere o número de valores e uma célula concreta no resultado.
Exercícios
Decidir quando agregar
Existem duas vendas de pão no Porto. Queres uma célula com a soma das quantidades desse par cidade-produto. Qual é a operação adequada?
Primeira pista
Mais uma pista
Ver solução
pivot_table(…, values=“quantidade”, aggfunc=“sum”) reúne as vendas. Não dependas da média por defeito.
- pivot_table com aggfunc="sum". Agrega os valores que têm o mesmo par de chaves.
- pivot sem agregação. Exige um valor único para cada célula.
- rename. Muda nomes, não reduz as duas vendas a uma célula.
Erros frequentes
Contar a transformação
Uma tabela tem três datas e duas colunas de produto. melt conserva a data e transforma ambas as colunas. Quantas linhas há no resultado, sem eliminar nulos?
Primeira pista
Mais uma pista
Ver solução
Há seis linhas. Cada uma identifica data, produto e quantidade.
Erros frequentes
Contar apenas as datas ou somar o número de datas ao de produtos.