Ir al contenido
wannacode

Resúmenes y valores faltantes

En resumen: Las agregaciones en NumPy (sum, mean, max, argmax) hacen un número a partir de muchos, axis dice qué dimensión desaparece, y NaN marca un valor faltante.

Problema

«¿Qué es lo que más vendemos?»

La caja manda un informe: cuántas unidades de cuatro productos vendimos cada semana, en las últimas seis semanas. Cada fila es una semana, cada columna un producto:

Pythondatos: las tablas de la tienda

El gerente pregunta tres cosas: cuánto vendimos en total, qué producto va mejor y qué semana fue la más fuerte. Luego manda también los ingresos por día, con un día que falta.

Cada respuesta es un número (o uno por producto), calculado a partir de muchos números. Eso se llama una agregación.

La idea

Un número a partir de muchos: sum, mean, min, max

Un arreglo tiene métodos que resumen todos sus valores: sum() para el total, mean() para la media, min() y max() para el menor y el mayor. Aquí están con los precios de los 25 productos. to_numpy() toma la columna como arreglo de NumPy:

Pythondatos: las tablas de la tienda

La suma de los precios sale 175.89999999999998, no 175,9. La computadora guarda los decimales en binario y 0,1 no se puede escribir exactamente, así que se acumulan errores diminutos. No son errores de los datos.

Para un informe redondeas: round(x, 2) da 2 decimales. El precio medio pasa a ser 7,04 €, como en describe() del primer vistazo.

Más precisamente, para curiosos

round es la función de Python y trabaja con un solo número. Un arreglo tiene el método .round(2) (o np.round(arr, 2)), que redondea cada número. Redondea al final, para mostrar: si redondeas a mitad de camino, el error de redondeo pasa a los pasos siguientes.

La idea

Cuál, no cuánto: argmax y argmin

max() te dice cuánto cuesta el producto más caro. Pero el gerente pregunta cuál es. argmax() da la posición del mayor valor, y argmin() la del menor. Con la posición tomas el nombre del arreglo de nombres:

Pythondatos: las tablas de la tienda

El más caro es el juego de cuchillos en la posición 22 (39 €), y el más barato es el bollo de mantequilla en la posición 2 (0,80 €). Las posiciones empiezan en 0, como en las listas.

1. prices.max() devuelve 39.0 y prices.argmax() devuelve 22. ¿Qué es 22?
Más precisamente, para curiosos

Si el mayor valor aparece varias veces, argmax da su primera posición. En el informe de caja, las semanas 1 y 4 tienen 103 unidades cada una, y argmin sobre las semanas da solo la semana 1. Si los empates importan, compruébalos con una máscara: week_totals == week_totals.min().

Míralo

A lo largo de qué dimensión: axis

sales.sum() suma las 24 celdas: 654 unidades en seis semanas. Para «qué producto» necesitas un total por cada columna, y para «qué semana» un total por cada fila. El parámetro axis dice cuál:

Pythondatos: las tablas de la tienda
  • axis=0 es la dimensión de las filas (las semanas). Las semanas se funden y queda un número por producto: el pan son 263 unidades, el café 39.
  • axis=1 es la dimensión de las columnas (los productos). Los productos se funden y queda un número por semana: de 103 a 120.

Aquí se confunde todo el mundo, porque «axis=0» suena a «por filas» y da un resultado por columna. La regla que no miente: axis es la dimensión que desaparece. La forma (6, 4) con axis=0 pierde el 6 y pasa a (4,), y con axis=1 pierde el 4 y pasa a (6,).

Lo mismo vale para mean, min, max, argmax y el resto. La media por semana de cada producto, redondeada a un decimal:

Pythondatos: las tablas de la tienda

Pruébalo

La semana más fuerte

¿Qué semana vendió más unidades en total? Pon el total de cada semana en week_totals y su número (de 1 a 6) en best_week.

Pythondatos: las tablas de la tienda

La idea

Cuánto hasta ahora: cumsum

A veces el gerente pregunta no «cuánto esta semana» sino «cuánto desde el principio hasta esta semana». Es la suma acumulada: cumsum() suma los números uno a uno y guarda cada suma parcial:

Pythondatos: las tablas de la tienda

Después de la tercera semana hemos vendido 319 unidades, y el último número, 654, es el total de sales.sum(). La suma acumulada es la línea que crece en los gráficos de «ventas en lo que va del año».

La idea

Un día que falta: NaN

Ahora los ingresos por día de la última semana. El miércoles la caja no mandó informe, así que en el lugar del miércoles hay un np.nan: el valor para «faltante» que viste en el primer vistazo. Esto le pasa a la media:

Pythondatos: las tablas de la tienda

La media normal es nan. Cualquier cuenta con NaN da NaN: ¿cuánto es 412,5 más «no sé»? No sé. NumPy no lanza ningún error; devuelve nan en silencio, y en un informe largo pasa desapercibido.

np.isnan(revenue) es una máscara que dice dónde faltan valores, y .sum() sobre ella los cuenta: 1 día. np.nanmean y np.nansum se saltan los NaN: los ingresos medios de los seis días conocidos son 494,70 €, y su suma es 2968,20 €. Esa suma es «lo que sabemos hasta ahora», no los ingresos de toda la semana: el miércoles no está en ella.

Míralo

Por qué no 0

La tentación es sustituir el valor que falta por 0 y seguir. np.nan_to_num hace justo eso:

Pythondatos: las tablas de la tienda

La media baja de 494,70 € a 424,03 €. El cero dice «el miércoles no vendimos nada», y eso no es verdad: la tienda estaba abierta, solo falta el informe. 0 no es «faltante». El cero es un valor, y NaN es la ausencia de un valor.

0 es la sustitución correcta solo cuando de verdad significa cero. Si la caja no manda ninguna línea para un producto que nadie compró, el hueco son cero ventas. Eso lo decide el significado de los datos, no el código.

Pruébalo

Una semana sin cuenta

La caja no mandó cuántos paquetes de café vendimos en la tercera semana. Pon en avg_coffee cuántos paquetes vendemos por semana, en promedio.

Pythondatos: las tablas de la tienda

Ejercicio

El informe para el gerente

Responde al gerente a partir del informe de caja. Pon en product_totals las unidades de cada producto en las seis semanas, en best_product el nombre del producto más vendido, y en avg_per_week cuántas unidades vende cada producto por semana en promedio, redondeado a un decimal.

Pythondatos: las tablas de la tienda

Test

Ponte a prueba

1. sales tiene la forma (6, 4): 6 semanas y 4 productos. ¿Qué forma tiene sales.mean(axis=0)?
2. En un arreglo con los ingresos por día, un valor es np.nan. ¿Qué da revenue.sum()?
3. ¿Por qué está mal sustituir los ingresos que faltan por 0 y luego calcular la media?
4. Las unidades por semana son [103, 104, 112]. ¿Qué da .cumsum()?

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