Pandas Pivot vs Melt: La forma correcta de reestructurar datos
Updated on
Reformatear datos suele ser el cuello de botella antes de analizar o graficar. Elegir mal puede duplicar filas, perder datos o producir tablas anchas difíciles de usar.
Enfoque PAS:
- Problema: Datos wide/long desordenados frenan gráficos y agregaciones.
- Agitar: Usar
pivotcon duplicados lanza errores; usarmeltsin cuidado multiplica filas o pierde identificadores. - Solución: Flujo tidy:
pivot_tablesi hay duplicados,pivotsi las claves son únicas,meltpara ir a long,stack/unstackpara ajustar MultiIndex.
Guía rápida
| Método | Dirección | Cuándo usar | ¿Maneja duplicados? |
|---|---|---|---|
pivot | long → wide | Claves únicas | 🚫 (falla con duplicados) |
pivot_table | long → wide | Se necesita agregación o hay duplicados | ✅ vía aggfunc |
melt | wide → long | Normalizar columnas a filas | N/A |
stack / unstack | wide ↔ long sobre niveles de índice | MultiIndex | N/A |
Datos de ejemplo
import pandas as pd
sales = pd.DataFrame({
"region": ["NA", "NA", "EU", "EU"],
"quarter": ["Q1", "Q2", "Q1", "Q2"],
"product": ["A", "A", "A", "A"],
"revenue": [120, 140, 110, 150],
"units": [10, 11, 9, 12],
})Formato ancho con pivot
wide = sales.pivot(index="region", columns="quarter", values="revenue")- Requiere combinaciones únicas de
region+quarter. - Usa
.reset_index()si necesitas aplanar después.
Ancho con agregación (pivot_table)
table = sales.pivot_table(
index="region",
columns="quarter",
values="revenue",
aggfunc="sum",
margins=True,
margins_name="Total"
)- Maneja duplicados agregando.
fill_value=0deja la tabla limpia para exportar.
Varios valores y agregaciones
multi = sales.pivot_table(
index="region",
columns="quarter",
values=["revenue", "units"],
aggfunc={"revenue": "sum", "units": "mean"},
)Aplanar columnas:
multi.columns = [f"{metric}_{col}" for metric, col in multi.columns]
multi = multi.reset_index()Formato largo con melt
long = sales.melt(
id_vars=["region", "quarter"],
value_vars=["revenue", "units"],
var_name="metric",
value_name="value",
)- Ideal para bibliotecas que esperan datos tidy (una variable por columna, una observación por fila).
- Controla qué columnas desanidar con
value_vars.
Stack y unstack para MultiIndex
stacked = table.stack()
unstacked = stacked.unstack()- Reorganiza niveles sin redefinir claves.
- Elige nivel con
stack(level="quarter")ounstack(level=-1).
Errores comunes
| Problema | Solución |
|---|---|
ValueError: Index contains duplicate entries con pivot | Usa pivot_table con una agregación. |
| Orden de columnas inesperado | Ordena: table = table.reindex(sorted(table.columns), axis=1). |
| MultiIndex difícil de leer | Aplana columnas tras pivot_table. |
| Valores faltantes tras reshape | Usa fill_value o stack(dropna=False) para conservar huecos. |
Consejos de flujo de trabajo
- Normaliza primero:
melt→groupby/agg→pivot_tablepara presentación. - Para gráficos, mantén los datos en largo; wide es mejor para reportes/exportes.
- Tras
pivot_table, exporta a Excel:table.to_excel("report.xlsx").
Guías relacionadas
Puntos clave
pivotcon claves únicas,pivot_tablecuando hay que agregar,meltpara ir a largo.- Aplana MultiIndex después de pivots complejos para exportar limpio.
- Combina reshape con
groupbypara obtener datasets listos rápido.