Distribuciones
En resumen: Una distribución muestra cómo se reparten todos los valores a la vez: un histograma y un diagrama de caja la muestran para una variable, y un diagrama de dispersión muestra la relación entre dos.
Problema
«¿Cuánto vale un pedido?»
El gerente quiere saber cuánto vale un pedido. Se ha calculado la media: 10,63 €. La publicidad se planificará para «el cliente típico con un pedido de unos 10 €».
Hay 10 459 pedidos vendidos (sin los cancelados), y 6736 de ellos están por debajo de la media. Casi dos de cada tres. ¿Cómo puede el «promedio» estar por encima de la mayoría? La respuesta la ves cuando miras todos los pedidos a la vez en lugar de un solo número.
La idea
Histograma
Cómo se reparten los valores, cuáles son comunes y cuáles raros, se llama distribución. Su imagen es el histograma: el eje x se divide en intervalos iguales, y cada barra es cuántos pedidos caen en su intervalo.
ax.hist(values, bins=30) hace 30 intervalos desde el valor más pequeño hasta el más grande y los cuenta. Devuelve tres cosas: la cantidad en cada intervalo, los bordes y las propias barras.
La primera barra va de 0,80 € a 3,40 € y contiene 1915 pedidos. La segunda, de 3,40 € a 5,99 €, es la más alta: 2122. Después las barras bajan, y a la derecha queda una franja fina de pedidos raros, hasta 78,70 €. Esa franja se llama cola. Una distribución con una cola larga a la derecha es normal en el dinero: muchas compras pequeñas y pocas grandes.
La idea
El número de intervalos cambia la imagen
Tú eliges bins, y un número distinto cuenta una historia distinta. Aquí están los mismos pedidos con 4 y con 80 intervalos:
Con 4 intervalos solo ves que 9091 pedidos están por debajo de 20,28 €, 1182 llegan hasta 39,75 €, y después casi no hay. Con 80 intervalos ves que la mayoría de los pedidos están entre 2 € y 8 €, y la cantidad cae con suavidad hacia la cola. Los picos (una barra alta, su vecina baja) vienen de los precios: algunos totales se forman con más frecuencia que otros.
No hay un único número correcto. Prueba unos cuantos y elige aquel en que se ve la forma y el ruido no la tapa. Para unos pocos miles de valores, 30–60 intervalos suele ser un buen comienzo.
Más precisamente, para curiosos
bins también puede ser una lista de bordes: bins=[0, 5, 10, 20, 40, 80]. Entonces los intervalos no son igual de anchos, y la altura engaña: un intervalo ancho recoge más pedidos solo porque es ancho. Con density=True la altura se divide entre el ancho del intervalo, y los intervalos anchos ya no engañan.
Pruébalo
Diciembre de cerca
¿Cómo son los pedidos de diciembre? Guarda en december los pedidos vendidos de diciembre y dibuja un histograma de su valor con 40 intervalos. Pon etiqueta al eje x.
Solución
import pandas as pd
import matplotlib.pyplot as plt
orders = pd.read_csv('year_orders.csv', parse_dates=['ordered_at'])
items = pd.read_csv('year_items.csv')
items['revenue'] = items['quantity'] * items['unit_price']
per_order = items.groupby('order_id', as_index=False).agg(
revenue=('revenue', 'sum'), lines=('product_id', 'size'), pieces=('quantity', 'sum'))
orders = orders.merge(per_order, left_on='id', right_on='order_id', how='left', validate='one_to_one')
# Los ingresos dejan fuera los pedidos cancelados.
sold = orders[orders['status'] != 'cancelled']
values = sold['revenue']
december = sold[sold['ordered_at'].dt.month == 12]
fig, ax = plt.subplots()
ax.hist(december['revenue'], bins=40)
ax.set_title('Pedidos de diciembre')
ax.set_xlabel('Valor del pedido, €')
ax.set_ylabel('Número de pedidos')sold[sold["ordered_at"].dt.month == 12] da 1211 pedidos, y ax.hist(december["revenue"], bins=40) los reparte de 0,80 € a 78,00 €. Además del pico de la izquierda hay un segundo bulto alrededor de 20–30 €: muchos de estos pedidos incluyen una tarjeta de regalo de 20 €, que se vende sobre todo en diciembre. Sin bins matplotlib usa 10 intervalos y se pierde la forma. Si tomas los pedidos de orders, el histograma contiene también 74 cancelados: 1285 en lugar de 1211.
La idea
Media y mediana
Ordena todos los pedidos del más pequeño al más grande. El valor justo en el medio es la mediana: la mitad de los pedidos está por debajo, la mitad por encima. values.median() la da.
Dibuja la media y la mediana en el histograma como líneas verticales. ax.axvline(x) dibuja una línea a lo largo de toda la altura del gráfico en el punto x:
La media es 10,63 €, y la mediana es 7,70 €. La mediana está donde está la mayor parte de las barras. La media está a su derecha: la cola de pedidos grandes la sube, porque cada euro de ellos entra en la suma. A la mediana le da igual que el pedido más grande sea de 78 € o de 7800 €.
Así que con dinero, tiempos y tamaños, donde hay cola, mira las dos. Si están lejos una de otra, la mediana está más cerca del «cliente típico».
La idea
Diagrama de caja
Un histograma es detallado, pero dos o cinco histogramas uno al lado del otro son difíciles de comparar. Un diagrama de caja (box plot) reduce una distribución a cinco cosas. Diciembre es el mes más fuerte: ¿son sus pedidos más grandes, o solo hay más?
Cómo se lee:
- la línea de la caja es la mediana: 8,60 € en diciembre y 7,60 € en los demás meses;
- la caja es la mitad central de los pedidos: un cuarto está por debajo, un cuarto por encima;
- los bigotes llegan hasta los últimos valores habituales;
- los círculos son pedidos inusualmente grandes.
La caja de diciembre es más alta y llega más arriba: ahí hay más pedidos grandes (regalos, sartenes, cuchillos). Así que la media cambia más que la mediana: 13,14 € frente a 10,30 €, mientras que la mediana es 8,60 € frente a 7,60 €. Diciembre tiene más pedidos y más grandes, pero la diferencia está sobre todo en la cola.
Más precisamente, para curiosos
Un bigote llega hasta el pedido más lejano que no esté a más de 1,5 alturas de caja de la caja. Todo lo que está más lejos es un círculo. Calcularás esta regla y la altura de la caja (IQR) con números en la lección sobre describir datos.
En versiones antiguas de matplotlib (anteriores a 3.9) las etiquetas se dan con labels= en lugar de tick_labels=.
La idea
Dispersión: dos números por pedido
¿Crece el dinero con el número de líneas del pedido? Aquí tienes dos números por pedido, y la pregunta es cómo se relacionan. La imagen es un diagrama de dispersión (scatter plot): cada pedido es un punto, x es un número, y es el otro. ax.scatter(x, y) lo dibuja.
A la izquierda todo está en columnas macizas. Miles de puntos están unos encima de otros, y no ves dónde hay muchos y dónde pocos. Esto se llama overplotting (solapamiento). A la derecha alpha=0.03 hace cada punto casi transparente: donde hay muchos, el color se acumula y queda oscuro.
Ahora ves que con cada línea el pedido crece unos 4–5 € de media: de 4,27 € con una línea (2517 pedidos) a 27,48 € con seis (145 pedidos). Pero los puntos de cada número de líneas se dispersan hacia arriba: un producto caro cuesta como diez baratos.
sharey=True da a los dos gráficos el mismo eje y, para que comparen con justicia.
Pruébalo
Unidades y valor
La columna pieces es el número de unidades del pedido (la suma de quantity). Dibuja un diagrama de dispersión: las unidades en x, el valor del pedido en y, con transparencia para que se vea dónde hay muchos pedidos. Pon etiqueta a los dos ejes.
Solución
import pandas as pd
import matplotlib.pyplot as plt
orders = pd.read_csv('year_orders.csv', parse_dates=['ordered_at'])
items = pd.read_csv('year_items.csv')
items['revenue'] = items['quantity'] * items['unit_price']
per_order = items.groupby('order_id', as_index=False).agg(
revenue=('revenue', 'sum'), lines=('product_id', 'size'), pieces=('quantity', 'sum'))
orders = orders.merge(per_order, left_on='id', right_on='order_id', how='left', validate='one_to_one')
# Los ingresos dejan fuera los pedidos cancelados.
sold = orders[orders['status'] != 'cancelled']
values = sold['revenue']
fig, ax = plt.subplots()
ax.scatter(sold['pieces'], sold['revenue'], alpha=0.05)
ax.set_title('Unidades y valor del pedido')
ax.set_xlabel('Unidades en el pedido')
ax.set_ylabel('Valor del pedido, €')ax.scatter(sold["pieces"], sold["revenue"], alpha=0.05) dibuja 10 459 puntos. Las unidades van de 1 a 14, y los puntos son más densos entre 1 y 5 unidades y por debajo de 20 €. Sin alpha las columnas son macizas, y un pedido con 14 unidades parece tan importante como los miles con 2.
Ejercicio
La respuesta para el gerente
El gerente quiere un solo gráfico: cuánto valen los pedidos y dónde están la media y la mediana. Guarda la media del valor de los pedidos vendidos en mean_value y la mediana en median_value. Dibuja un histograma con 50 intervalos y los dos valores como líneas verticales, con una leyenda.
Solución
import pandas as pd
import matplotlib.pyplot as plt
orders = pd.read_csv('year_orders.csv', parse_dates=['ordered_at'])
items = pd.read_csv('year_items.csv')
items['revenue'] = items['quantity'] * items['unit_price']
per_order = items.groupby('order_id', as_index=False).agg(
revenue=('revenue', 'sum'), lines=('product_id', 'size'), pieces=('quantity', 'sum'))
orders = orders.merge(per_order, left_on='id', right_on='order_id', how='left', validate='one_to_one')
# Los ingresos dejan fuera los pedidos cancelados.
sold = orders[orders['status'] != 'cancelled']
values = sold['revenue']
mean_value = values.mean()
median_value = values.median()
fig, ax = plt.subplots()
ax.hist(values, bins=50, color='lightgray')
ax.axvline(mean_value, color='black', label='media')
ax.axvline(median_value, color='black', linestyle='--', label='mediana')
ax.set_title('Cuánto vale un pedido')
ax.set_xlabel('Valor del pedido, €')
ax.legend()
print(round(mean_value, 2), round(median_value, 2))La media es 10,63 €, y la mediana es 7,70 €. La mitad de los pedidos está por debajo de 7,70 €, y 6736 de 10 459 están por debajo de la media. El pedido típico está más cerca de 7,70 €, y la media es mayor por la cola de pedidos grandes de hasta 78,70 €. Si calculas con orders, los cancelados también entran en los números: la media sale 10,61 €.
Test
Ponte a prueba
Lecciones relacionadas
Sección «Lecciones relacionadas»- Se basa en: Grupos: groupby · Unir tablas: merge · El primer gráfico · Qué gráfico para qué pregunta
- Continúa en: Describir los datos · Muestra y población · Intervalos de confianza · Correlación y causa
- Ejercicios sobre el tema: Gráficos