Skip to content

Pandas MultiIndex: Guía de indexación jerárquica

Updated on

MultiIndex desbloquea jerarquías ordenadas para datos de panel, series temporales y datos remodelados, pero muchas personas lo evitan porque el slicing parece frágil y el orden de los niveles puede resultar confuso.

  • Problema: Las dimensiones anidadas (región + año, símbolo + campo) se vuelven desordenadas cuando se almacenan en columnas planas o en tablas anchas.
  • Agitación: Los reshapes ad hoc generan nombres de columnas duplicados, ordenamientos rotos y errores al seleccionar por varias claves.
  • Solución: Usar un pequeño conjunto de patrones repetibles: construir el MultiIndex con set_index, segmentar de forma segura con .loc/.xs, reordenar con swaplevel/reorder_levels, y remodelar con stack/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)


Referencia rápida

TareaMétodoFragmento
Construir niveles desde columnasset_indexdf.set_index(["region", "year"]).sort_index()
Desde producto cartesianopd.MultiIndex.from_productpd.MultiIndex.from_product([regions, years], names=["region", "year"])
Hacer slice por nivel.loc o .xsdf.loc[("EMEA", 2024)] o df.xs("EMEA", level="region")
Reordenar nivelesswaplevel, reorder_levelsdf.swaplevel("region", "year")
Eliminar o aplanardroplevel, reset_indexdf.droplevel("year"), df.reset_index()
Remodelar wide/longunstack / stackdf.unstack("field"), df.stack("field")

Datos de ejemplo

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

Creación de estructuras MultiIndex

A partir de columnas existentes

sales = raw_df.set_index(["region", "year"]).sort_index()
  • Usa sort_index() para obtener slicing predecible a través de los niveles.
  • Mantén como columnas normales aquellas que deban seguir siendo valores (por ejemplo, montos).

Desde producto o tuplas

idx = pd.MultiIndex.from_product(
    [["EMEA", "NA"], [2023, 2024]],
    names=["region", "year"],
)
frame = pd.DataFrame(index=idx, columns=["revenue"]).sort_index()

from_product garantiza que exista cada combinación; usa from_tuples cuando ya tienes las parejas.


Selección con MultiIndex

# Una ruta única a través de la jerarquía
emea_2024 = df.loc[("EMEA", 2024)]
 
# Sección transversal por un nivel, conservando el resto
emea = df.xs("EMEA", level="region")
 
# Selección parcial con slices (requiere índice ordenado)
idx = pd.IndexSlice
subset = df.loc[idx[:, 2024, :], :]
  • .xs (cross-section) es cómodo cuando quieres conservar intactos los niveles restantes.
  • Para jerarquías de series temporales, ordena el índice y haz slicing con IndexSlice para mayor legibilidad.

Reordenar y limpiar niveles

# Traer year antes de region
reordered = df.swaplevel("region", "year").sort_index(level=["year", "region"])
 
# Reordenación explícita para 3+ niveles
df_reordered = df.reorder_levels(["metric", "region", "year"])
 
# Eliminar un nivel cuando ya no lo necesitas
flat = df.droplevel("metric")
  • swaplevel es rápido para intercambiar dos niveles adyacentes; reorder_levels maneja órdenes arbitrarios.
  • Después de reordenar, llama a sort_index(level=...) para restaurar un orden monótono adecuado para slicing.

Remodelar con Stack y Unstack

Transforma tablas anchas en formato long ordenado (y viceversa) usando niveles del índice como pivotes.

wide = df.unstack("metric")  # los valores de metric pasan a ser columnas
long_again = wide.stack("metric")
  • Usa fill_value= en unstack para reemplazar combinaciones faltantes.
  • Para operaciones tipo pivot sobre columnas, combina set_index([...]).unstack() con stack() en lugar de bucles manuales.

Cuándo usar MultiIndex vs. columnas

EscenarioMultiIndexColumnas simples
Las etiquetas jerárquicas dirigen el slicing (región → año → métrica)✅ Encaje natural para .loc/.xs⚠️ Requiere filtros/joins repetidos
Maquetación de reportes anchosunstack para convertir niveles en columnas bajo demanda⚠️ Riesgo de nombres de columnas duplicados
Joins frecuentes sobre claves⚠️ Haz reset primero y luego merge✅ Mantén las claves como columnas para joins
Exportar a CSV/Parquetreset_index() antes de escribir✅ Sin paso adicional

Regla práctica: almacena datos con claves claras como columnas para intercambio; apóyate en MultiIndex cuando el slicing jerárquico o el reshaping sea el flujo de trabajo principal.


Errores comunes y cómo corregirlos

  • Índice no ordenado bloquea el slicing: llama a sort_index(level=[...]) antes de hacer slices parciales.
  • Niveles sin nombre: establece index.names (o names= en set_index) para que los slices y los reset sean claros.
  • Salida difícil de leer: df.index.to_frame() expone los niveles como columnas para inspección, y reset_index() aplana cuando necesitas volver a columnas simples.

Estandarizando cómo construyes, segmentas, reordenas y remodelas objetos MultiIndex, obtienes jerarquías ordenadas sin la confusión habitual. Combina estos patrones con guías de reshaping como pandas-pivot-melt y utilidades para series temporales como pandas-resample para mantener datos multidimensionales manejables de punta a punta.