Ir al contenido
wannacode

Ancho y largo: pivot_table y melt

En resumen: pivot_table hace una tabla ancha con una columna para cada categoría, y melt devuelve la larga con una fila para cada hecho; la forma la eliges según la pregunta.

Problema

«Dámelo por mes y categoría»

El gerente quiere los ingresos del año en una tabla: los meses hacia abajo, las categorías hacia la derecha, como en Excel. Sabes cómo: unir las líneas con los pedidos, los productos y las categorías (merge) y agrupar por dos claves. Los pedidos cancelados no son ingresos, así que los quitas. La tarjeta de regalo no tiene categoría y recibe un nombre propio, o se caería de los grupos:

Pythondatos: las tablas de la tienda

Los números son correctos, pero son 84 filas: 12 meses por 7 categorías, una debajo de otra. Para comparar enero con julio, buscas en la lista con los ojos. La tabla que quiere el gerente tiene 12 filas y 7 columnas con los mismos 84 números.

El mes aquí es su número: 1 es enero de 2026, y 11 y 12 son noviembre y diciembre de 2025.

La idea

Larga y ancha

Los mismos números pueden estar en dos formas:

  • Larga: una fila para cada hecho. Las columnas son month, category y revenue, y cada par mes–categoría es una fila aparte.
  • Ancha: una fila para cada mes y una columna para cada categoría. La categoría ya no es una columna: sus valores se han convertido en nombres de columna.

De larga a ancha, con el resultado de groupby, se hace en una línea: unstack() toma el último nivel del índice (la categoría) y lo convierte en columnas:

Pythondatos: las tablas de la tienda

La forma es (12, 7): 12 meses y 7 categorías. Enero: 593 € cocina, 2038 € lácteos, 1225 € bebidas.

La idea

Directo a ancha: pivot_table

pivot_table agrupa y dispone a la vez. Le dices cuatro cosas:

  • index: qué va en las filas (el mes);
  • columns: qué se convierte en columnas (la categoría);
  • values: con qué columna trabaja (los ingresos);
  • aggfunc: cómo lo calcula ('sum').
Pythondatos: las tablas de la tienda

Ahora se lee de un vistazo. Diciembre es el pico: la cocina hace 3241 €, más de 4 veces un mes normal, y la tarjeta de regalo 2160 €. El verano trae bebidas y fruta: las bebidas son 1756 € en julio frente a 1225 € en enero. Septiembre es flojo casi en todo. Por qué, lo descubriremos en el proyecto.

Más precisamente, para curiosos

También existe pivot sin «table»: solo dispone y no suma. Si un par mes–categoría aparece en más de una fila, pivot se detiene con un error, mientras que pivot_table las combina con aggfunc. Para líneas en bruto necesitas pivot_table.

Pruébalo

Unidades por categoría

¿Cuántas unidades vendió cada categoría cada mes? Guarda en units una tabla con las categorías en las filas y los meses en las columnas.

Pythondatos: las tablas de la tienda

La idea

Celdas vacías: fill_value

En la tabla ancha cada par tiene una celda, aunque los datos no tengan ese par. Aquí está cuánto compró cada cliente de cada categoría en los 60 pedidos:

Pythondatos: las tablas de la tienda

35 celdas son NaN. El cliente 3 no compró pan, limpieza ni bebidas. Aquí vacío significa «cero compras», no «no lo sabemos». Por eso es correcto sustituirlo por cero: fill_value=0.

Pythondatos: las tablas de la tienda

Es el caso de la lección sobre resúmenes en el que 0 es el sustituto correcto: el cero significa de verdad cero. Si la celda estuviera vacía porque faltaba un informe, el cero mentiría.

La idea

Los totales: margins

margins=True añade una fila y una columna All con los totales. Aquí se muestran dos de las categorías y el total:

Pythondatos: las tablas de la tienda

La columna All son los ingresos del mes, y la fila All son los ingresos de la categoría en el año: 11 304 € cocina, 17 811 € bebidas. En la esquina está el total: 111 186,20 €. Septiembre es 7129 €, menos que agosto (8813 €) y octubre (9920 €).

La idea

De vuelta a larga: melt

El gerente envía el plan para los próximos tres meses. La tabla viene de Excel y es ancha: una fila por categoría y una columna por mes.

Una tabla ancha es buena para leer, pero no para trabajar. El mes no es una columna, está en los nombres de las columnas, y no hay nada por lo que agrupar. melt la funde de vuelta en una larga: id_vars es la columna que se queda, var_name pone nombre a la columna con los antiguos nombres de columna, y value_name a la columna con los números:

Pythondatos: las tablas de la tienda

7 filas y 4 columnas pasan a 21 filas y 3 columnas: cada número del plan es una fila aparte. Ahora el mes es una columna, y groupby funciona:

Pythondatos: las tablas de la tienda

El plan de diciembre es 16 650 €, y el de noviembre 9700 €.

Pruébalo

Qué forma para qué

1. Tienes una tabla larga plan_long con las columnas category, month y plan. ¿Cómo obtienes el plan de cada mes?
2. Quieres una línea por categoría a lo largo de los meses con df.plot(), que dibuja una línea para cada columna. ¿Qué tabla le das?

Ejercicio

El informe para el gerente

Haz el informe de la primera tarjeta: report con los ingresos por mes (filas) y categoría (columnas), con los totales All. Después guarda en dec_share qué parte de los ingresos del año es diciembre.

Pythondatos: las tablas de la tienda

¿Cuál es el plan de los tres meses en total para cada categoría? Haz plan largo (plan_long con las columnas category, month y plan) y guarda el total de cada categoría en per_category.

Pythondatos: las tablas de la tienda

Test

Ponte a prueba

1. ¿Qué calcula pivot_table si no le das aggfunc?
2. En la tabla «cliente × categoría», el cliente 3 no compró bebidas, y la celda es NaN. ¿Cuándo es correcto fill_value=0?
3. Una tabla de Excel tiene las columnas category, 2026-11, 2026-12 y 2027-01. ¿Qué la hace larga?
4. ¿Qué añade margins=True?

Creado por Ivo Gergov como parte de la campaña de Evo Tech por una educación accesible en programación ·