Este post viene código en python para hacer y personalizar uno de los gráficos más potentes y simples que existen. Puedes replicar todo lo que viene aquí en una notebook en
¿Qué son los diagrama de caja y bigote?
Son una forma gráfica y estandarizada de mostrar la distribución de los datos basado en 5 números clave:
- Media (Q2). Es el valor medio de nuestra información.
- Mínimo y máximo. Estos generan las patitas en los extremos del gráfico.
- Primer y Tercer cuartil (Percentil 25 y 75, respectivamente).
En ocasiones el gráfico mostrará algunos puntos adicionales, que se consideran los valores atípicos (outliers). El siguiente gráfico te puede ayudar a identificar estos elementos.
¿Para qué se usan?
Los gráficos de caja y bigotes se usan para
- Identificar valores atípicos y anomalías en los datos.
- Encontrar sesgos en los datos
- Entender de un vistazo los rangos que ocupa la información y cómo se distribuye.
Se pueden crear gráficos con varios diagramas de caja y bigotes. Estos ayudan a realizar una comparación de los datos y su distribución y compararlos por clasificación.
Cómo hacer un gráfico de caja y bigotes en Python
Comencemos por la creación de dos conjuntos de datos. Para tener certeza de antemano de la forma en la que se distribuyen los datos, usaremos una simulación.
El siguiente bloque de código crea dos arreglos de datos distribuidos normalmente alrededor de cero. Para diferenciarlos, les sumamos y restamos una unidad.
import numpy as np
np.random.seed(1)
b1 = np.random.randn(100) - 1
b2 = np.random.randn(100) + 1
Listo. Ahora podemos visualizar los gráficos que generamos. Usaremos el módulo maplotlib.pyplot
para esto. Veamos cómo se ve una de las variables.
import matplotlib.pyplot as plt
plt.boxplot(x = b1, vert = False)
Veamos el gráfico que generó y comparemos con lo que sabemos que hace el diagrama según la definición anterior. Primero, obtengamos la media, representada en la línea roja del centro.
print(np.median(b1))
# -0.9359260884377059
Como definimos la variable b1
, esperaríamos que la mediana estaría cercana a -1. Entre más grande sea la simulación, este número se debería acercar aún más.
El siguiente código muestra los cuartiles Q1 y Q3, que representan el rango intercuartílico (la zona de la caja).
q1 = np.quantile(b1, 0.25)
q3 = np.quantile(b1, 0.75)
print(q1, q3)
# -1.6138175212245889 -0.36258965920138087
¿Logras ver cómo estas medidas corresponden a las líneas de la caja? Veamos ahora los mínimos y máximos como los definimos anteriormente en la figura.
iqr = np.quantile(b1, 0.75) - np.quantile(b1, 0.25)
min = q1 - 1.5 * iqr
max = q3 + 1.5 * iqr
print(min, max)
# -3.4906593142594007 1.5142521338334312
Enchúlame la gráfica
Vamos a personalizar el gráfico. Es posible añadir estilo, colores y otras características.
Primero veamos cómo se vería el gráfico con datos atípicos. Incluir datos a tu base no es algo que debieras hacer en la realidad, es sólo con fines ilustrativos.
b1 = np.append(b1, 1.8)
punto_rojo = dict(markerfacecolor='red', marker='o')
plt.boxplot(x = b1, vert = False, flierprops=punto_rojo)
La primera línea del código agrega un punto en la posición 1.8, que gracias a la estimación del máximo en la sección pasada sabemos que es mayor.
Nota que al definir el punto rojo le he indicado con 'red'
el color que deseo. Puedes seleccionar entre los colores básicos o puedes personalizarlo con códigos hexadecimales.
Es posible modificarla forma de la gráfica para identificar la media. El siguiente gráfico “aprieta” la caja en la media para hacerlo parecer mas a un reloj de arena. También incluimos un rombo verde para identificar la mediana.
mean_shape = dict(markerfacecolor='green', marker='D', markeredgecolor='green')
plt.boxplot(x = b1, vert = False, flierprops=punto_rojo,
showmeans=True, meanprops=mean_shape, notch=True)
Múltiples diagramas en una figura
Una de las ventajas del diagrama de caja y bigote es poder comparar las distribuciones de múltiples variables. Primero volvemos a crear las variables y las colocamos en un objeto tipo DataFrame de pandas.
import numpy as np
import pandas as pd
np.random.seed(1)
b1 = np.random.randn(100) - 1
b2 = np.random.randn(100) + 1
df = pd.DataFrame({'b1':b1, 'b2':b2})
Pandas tiene su propio método para crear diagramas de caja y bigotes que permite trabajar directamente sobre los datos.
df[['b1', 'b2']].plot(kind = 'box', showmeans = True)