Autor: Luis Fernando Apáez Álvarez
-Curso PyM-
Clase 2: Librería Seaborn (Parte II)
Fecha: 08 de diciembre del 2022
En esta clase veremos formas de visualizar gráficos de variables categóricas con más profundidad.
Este tipo de gráficos son utilizados cuando queremos hacer comparaciones entre diferentes grupos. Recordemos que en el principio de la clase anterior realizamos este tipo de gráficos. La diferencia ahora para esta clase es que utilizaremos la función catplot()
la cual juega un papel muy similar a relplot()
, pero donde catplot()
está destinada para gráficos de variables categóricas.
Para ver ejemplo carguemos el siguiente conjunto de datos:
import seaborn as sns
df_tips = sns.load_dataset('tips')
df_tips.head()
total_bill | tip | sex | smoker | day | time | size | |
---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
Después, realizaremos un gráfico de conteo para la variable smoker
utilizando la función catplot()
como sigue
# Primero realizamos el grafico como lo hicimos
# en la clase pasada
ax = sns.countplot(data=df_tips,
x='smoker')
# luego utilizamos la funcion catplot()
ax = sns.catplot(data=df_tips,
x='smoker',
kind='count')
Podemos cambiar el orden de las categorías en el gráfico
# luego utilizamos la funcion catplot()
ax = sns.catplot(data=df_tips,
x='smoker',
order=['No', 'Yes'],
kind='count')
Veamos otro ejemplo:
# luego utilizamos la funcion catplot()
ax = sns.catplot(data=df_tips,
x='day',
kind='count')
En el cual puede verse que hubo más personas el sábado y el domingo. Además
# luego utilizamos la funcion catplot()
ax = sns.catplot(data=df_tips,
x='time',
kind='count')
hay más personas para la hora de la cena.
Por otro lado, los diagramas de barras son similares a los gráficos de conteo, pero éstos muestran la media de una variable cuantitativa entre las observaciones de cada categoría. Por ejemplo
# diagrama de barras utilizando catplot
ax = sns.catplot(data=df_tips,
# variable categorica
x='day',
# variable cuantitativa
y='total_bill',
kind='bar')
lo cual nos muestra los promedios de las facturas para cada día. Asimismo, puede verse un intervalo de confianza para ese promedio.
Podemos desactivar esos intervalos de confianza para no visualizarlos
# diagrama de barras utilizando catplot
ax = sns.catplot(data=df_tips,
# variable categorica
x='day',
# variable cuantitativa
y='total_bill',
ci=None,
kind='bar')
Podemos cambiar la horientación de las barras cambiando el orden de definición de las variables en cuestión
# diagrama de barras utilizando catplot
ax = sns.catplot(data=df_tips,
# variable cuantitativa
x='total_bill',
# variable categorica
y='day',
kind='bar')
Los diagramas de caja muestran la distribución de datos cuantitativos. Éstos son utilizados para comparar la distribución de una variable cuantitativa a tráves de grupos de una variable categórica. Veamos un ejemplo:
# diagrama de barras utilizando catplot
ax = sns.catplot(data=df_tips,
# variable categorica
x='time',
# variable cuantitativa
y='total_bill',
kind='box')
donde las cajas de colores de los boxplots representan del percentil 25 al 75 y las línea de en medio representan la mediana; los bigotes dan una idea de la dispersión de la distribucion y los puntos flotantes son valores atípicos.
El percentil 25 nos diría que el 75% de los totales de facturas fueron superiores a poco más de 13 dólares; el percentil 75 nos dice que el 75$ de los totales de facturas fueron inferioreres a poco menos de 20 dólares. Luego, el rango intercuartílico se obtiene de restar los percentiles 75 y 25. La longitud del bigote inferior se obtiene de calcular la resta entre el percentil 25 y 1.5 veces el rango intercuartílico; la longitud del bigote superior se obtiene de calcular la resta del percentil 75 más 1.5 veces el rango intercuartílico. De lo anterior diremos que 1.5 es el factor que modifica las longitudes de los bigotes.
Del boxplot anterior podemos decir que la mediana de la factura total es más alta para la cena que para el almuerzo, pero la dispersion tambien es mayor pues los bigotes son más grandes.
Podemos configurar para que no se vean los valores atípicos
ax = sns.catplot(data=df_tips,
x='time',
y='total_bill',
# configuracion para que no se vean los valores
# atipicos
sym='',
kind='box')
Podemos modificar el factor para cambiar la longitud de los bigotes
ax = sns.catplot(data=df_tips,
x='time',
y='total_bill',
# configuracion un factor de 2
whis=2.0,
kind='box')
donde notamos que las longitudes de los bigoteshan aumentado.
Estos gráficos muestran la media de las observaciones de una variable cuantitativa para cada categoría, donde dichas medias son trazadas como puntos. Luego, cada punto que representa a una media tiene graficado una línea vertical que representa un intervalo de confianza para esa media. Dichos gráficos representan de manera similar la misma información respecto a los gráficos de barras, no obstante, puede ser más conveniente en algunos casos utilizar gráficos de puntos sobre diagramas de barras. Para ver un ejemplo que represente lo último dicho agregaremos una columna nueva al dataset con el que estamos trabajando
# agregaremos una columna de edad
# importacion necesaria para crear numeros aleatorios
import numpy as np
df_tips['age'] = [np.random.randint(18,80) for i in range(df_tips.shape[0])]
df_tips
total_bill | tip | sex | smoker | day | time | size | age | |
---|---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 | 75 |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 | 61 |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 | 79 |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 | 31 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 | 21 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
239 | 29.03 | 5.92 | Male | No | Sat | Dinner | 3 | 77 |
240 | 27.18 | 2.00 | Female | Yes | Sat | Dinner | 2 | 30 |
241 | 22.67 | 2.00 | Male | Yes | Sat | Dinner | 2 | 44 |
242 | 17.82 | 1.75 | Male | No | Sat | Dinner | 2 | 74 |
243 | 18.78 | 3.00 | Female | No | Thur | Dinner | 2 | 43 |
244 rows × 8 columns
Luego, agregaremos una columna más donde categorizaremos la edad:
# definimos una funcion
def cat(x):
if x < 30 and x >= 18:
return '18-30'
elif x < 60 and x >= 30:
return '30-60'
else:
return '60+'
# creamos la columna nueva
df_tips['c_age'] = df_tips.age.apply(lambda x: cat(x))
df_tips
total_bill | tip | sex | smoker | day | time | size | age | c_age | |
---|---|---|---|---|---|---|---|---|---|
0 | 16.99 | 1.01 | Female | No | Sun | Dinner | 2 | 75 | 60+ |
1 | 10.34 | 1.66 | Male | No | Sun | Dinner | 3 | 61 | 60+ |
2 | 21.01 | 3.50 | Male | No | Sun | Dinner | 3 | 79 | 60+ |
3 | 23.68 | 3.31 | Male | No | Sun | Dinner | 2 | 31 | 30-60 |
4 | 24.59 | 3.61 | Female | No | Sun | Dinner | 4 | 21 | 18-30 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
239 | 29.03 | 5.92 | Male | No | Sat | Dinner | 3 | 77 | 60+ |
240 | 27.18 | 2.00 | Female | Yes | Sat | Dinner | 2 | 30 | 30-60 |
241 | 22.67 | 2.00 | Male | Yes | Sat | Dinner | 2 | 44 | 30-60 |
242 | 17.82 | 1.75 | Male | No | Sat | Dinner | 2 | 74 | 60+ |
243 | 18.78 | 3.00 | Female | No | Thur | Dinner | 2 | 43 | 30-60 |
244 rows × 9 columns
Posteriormente realizamos un gráfico de barras donde veremos el total de la factura para cada categoría de edad y donde separaremos a las personas en fumadores y no fumadores:
ax = sns.catplot(data=df_tips,
# variable categorica
x='c_age',
# variable cuantitativa
y='total_bill',
# separamos las personas de acuerdo
# a la columna smoker
hue='smoker',
kind='bar')
notamos que el total de las facturas es, en promedio, mayor para las mersonas mayores de 60 años fumadoras que el resto de personas.
Veamos el equivalente pero ahora realizando el gráfico de puntos
ax = sns.catplot(data=df_tips,
# variable categorica
x='c_age',
# variable cuantitativa
y='total_bill',
# separamos las personas de acuerdo
# a la columna smoker
hue='smoker',
kind='point')
Del mismo modo podemos ver las medias del total de la factura por categoría, referente a las categorías de la columna c_age
, y también podemos ver los intervalos de confianza para esas medias.
De nuevo, el gráfico de barras y de líneas es similar, pero del gráfico de líneas, en este caso, podemos extraer de manera más sencilla información relevante. Por ejemplo, podemos decir que el promedio del total de factura es mayor para los fumadores respecto con los no fumadores, para los casos en que las edades entán entre los 18-30 y 60+; caso contrario para las edades entre 30-60, donde los no fumadores tiene en promedio un mayor total de la factura.
Una diferencia clara entre el gráfico de líneas respecto al gráfico de barras es que en el gráfico de barras tenemos la información de los fumadores y no fumadores en dos barras, en cambio, en el gráfico de puntos la información de los fumadores y los no fumadores se encuentra en el mismo eje.
Podemos quitar las líneas que unen los puntos de las medias.
ax = sns.catplot(data=df_tips,
# variable categorica
x='c_age',
# variable cuantitativa
y='total_bill',
# separamos las personas de acuerdo
# a la columna smoker
hue='smoker',
join=False,
kind='point')
Podemos cambiar que los puntos representen la media y en su lugar representen otro estimador. Por ejemplo
ax = sns.catplot(data=df_tips,
x='c_age',
y='total_bill',
hue='smoker',
join=False,
# el estimador ahora sera la mediana
estimator=np.median,
kind='point')
Cabe resaltar que la mediana no cambia mucho a pesar de los valores atípicos, en cambio, la media sí que puede verse afectada por los valores atípicos.
Podemos personalizar también la forma en que se ven los intervalos de confianza
ax = sns.catplot(data=df_tips,
x='c_age',
y='total_bill',
hue='smoker',
join=False,
estimator=np.median,
# mostramos lineas horizontales en los
# extremos de los intervalos de
# confianza
capsize=0.2,
kind='point')
O también podemos quitar los intervalos de confianza
ax = sns.catplot(data=df_tips,
x='c_age',
y='total_bill',
hue='smoker',
join=False,
estimator=np.median,
# quitamos los intervalos de confianza
ci=None,
kind='point')