Pandas MultiIndex: Guia de Indexação Hierárquica
Updated on
MultiIndex desbloqueia hierarquias organizadas para dados de painel, séries temporais e dados reprojetados, mas muitos usuários evitam usá-lo porque a forma de fatiar parece frágil e a ordem dos níveis pode ficar confusa.
- Problema: Dimensões aninhadas (região + ano, símbolo + campo) ficam confusas quando armazenadas em colunas simples ou em tabelas largas.
- Agravante: Reestruturações ad hoc levam a nomes de colunas duplicados, ordenações quebradas e erros ao selecionar por múltiplas chaves.
- Solução: Use um pequeno conjunto de padrões repetíveis: construa o MultiIndex com
set_index, faça fatias com segurança usando.loc/.xs, reordene comswaplevel/reorder_levelse reprocesse comstack/unstack.
Want an AI agent that understands your pandas notebooks and MultiIndex slicing?
RunCell is a JupyterLab AI agent that can read your code, analyze DataFrames, understand notebook context, debug errors, and even generate & execute code for you. It works directly inside JupyterLab—no switching windows or copy-pasting.
👉 Try RunCell: runcell.dev (opens in a new tab)
Referência rápida
| Tarefa | Método | Trecho |
|---|---|---|
| Construir níveis a partir de colunas | set_index | df.set_index(["region", "year"]).sort_index() |
| A partir de produto cartesiano | pd.MultiIndex.from_product | pd.MultiIndex.from_product([regions, years], names=["region", "year"]) |
| Fatiar por nível | .loc ou .xs | df.loc[("EMEA", 2024)] ou df.xs("EMEA", level="region") |
| Reordenar níveis | swaplevel, reorder_levels | df.swaplevel("region", "year") |
| Remover ou achatar | droplevel, reset_index | df.droplevel("year"), df.reset_index() |
| Reformatar wide/long | unstack / stack | df.unstack("field"), df.stack("field") |
Dados de exemplo
import pandas as pd
records = [
("EMEA", 2023, "revenue", 120),
("EMEA", 2023, "profit", 25),
("EMEA", 2024, "revenue", 140),
("NA", 2024, "revenue", 210),
("NA", 2024, "profit", 50),
]
df = (
pd.DataFrame(records, columns=["region", "year", "metric", "value"])
.set_index(["region", "year", "metric"])
.sort_index()
)Criando estruturas MultiIndex
A partir de colunas existentes
sales = raw_df.set_index(["region", "year"]).sort_index()- Use
sort_index()para fatiamento previsível entre níveis. - Mantenha fora do índice as colunas que devem continuar sendo regulares (por exemplo, valores numéricos).
A partir de produto ou tuplas
idx = pd.MultiIndex.from_product(
[["EMEA", "NA"], [2023, 2024]],
names=["region", "year"],
)
frame = pd.DataFrame(index=idx, columns=["revenue"]).sort_index()from_product garante que toda combinação exista; use from_tuples quando você já tem os pares.
Selecionando com MultiIndex
# Um único caminho através da hierarquia
emea_2024 = df.loc[("EMEA", 2024)]
# Seção transversal por um nível, mantendo o restante
emea = df.xs("EMEA", level="region")
# Seleção parcial com slices (requer índice ordenado)
idx = pd.IndexSlice
subset = df.loc[idx[:, 2024, :], :].xs(cross-section) é conveniente quando você quer manter os demais níveis intactos.- Para hierarquias de séries temporais, ordene o índice e faça fatias com
IndexSlicepara ganhar legibilidade.
Reordenando e limpando níveis
# Trazer year antes de region
reordered = df.swaplevel("region", "year").sort_index(level=["year", "region"])
# Reordenação explícita para 3+ níveis
df_reordered = df.reorder_levels(["metric", "region", "year"])
# Remover um nível quando ele não for mais necessário
flat = df.droplevel("metric")swaplevelé rápido para trocar dois níveis adjacentes;reorder_levelslida com ordens arbitrárias.- Depois de reordenar, chame
sort_index(level=...)para restaurar a ordem monótona necessária para fatiamento.
Reformatando com Stack e Unstack
Transforme tabelas largas em formato longo organizado (e vice-versa) usando níveis do índice como pivôs.
wide = df.unstack("metric") # valores de metric viram colunas
long_again = wide.stack("metric")- Use
fill_value=emunstackpara substituir combinações ausentes. - Para operações do tipo pivot em colunas, combine
set_index([...]).unstack()comstack()em vez de laços manuais.
Quando usar MultiIndex vs. colunas
| Cenário | MultiIndex | Colunas simples |
|---|---|---|
| Rótulos hierárquicos dirigem o fatiamento (region → year → metric) | ✅ Encaixe natural para .loc/.xs | ⚠️ Exige filtros/joins repetidos |
| Layout de relatório wide | ✅ unstack para colunas sob demanda | ⚠️ Risco de nomes de colunas duplicados |
| Merges frequentes em chaves | ⚠️ Faça reset antes, depois faça merge | ✅ Mantenha chaves como colunas para joins |
| Exportar para CSV/Parquet | ✅ reset_index() antes de gravar | ✅ Nenhum passo extra |
Regra prática: armazene dados com chaves claras como colunas para intercâmbio; use MultiIndex quando fatiamento hierárquico ou reestruturação forem o principal fluxo de trabalho.
Armadilhas comuns e correções
- Índice não ordenado bloqueia fatiamento: chame
sort_index(level=[...])antes de fatias parciais. - Níveis sem nome: defina
index.names(ounames=emset_index) para manter claras as fatias e os resets. - Saída difícil de ler:
df.index.to_frame()expõe os níveis como colunas para inspeção, ereset_index()achata tudo quando você precisa voltar a colunas simples.
Ao padronizar como você constrói, fatia, reordena e reprojeta objetos MultiIndex, você obtém hierarquias organizadas sem a confusão habitual. Combine esses padrões com guias de reestruturação como pandas-pivot-melt e utilitários de séries temporais como pandas-resample para manter dados multidimensionais controlados de ponta a ponta.