4. Gráficos categóricos

Los gráficos categóricos permiten comparar distribuciones y promedios entre grupos. Seaborn ofrece atajos de alto nivel que entienden directamente tus DataFrames y variables categóricas.

Todos los ejemplos incluyen imports y set_theme para que puedas copiar/pegar y ejecutar con Seaborn ≥ 0.12/0.13.

4.1 Diagramas de barras — barplot

Muestran por defecto la media de una variable numérica para cada categoría y un intervalo (controlado por errorbar).

A) Barras básicas (media + error)

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

sns.barplot(data=tips, x="day", y="total_bill", errorbar=("pi", 95))  # intervalo percentil 95%
plt.title("Cuenta promedio por día (con intervalo 95%)")
plt.xlabel("Día")
plt.ylabel("Promedio de total_bill (USD)")
plt.show()
Gráfico de barras básico

B) Barras por subgrupo (hue) y distinto estimador

import seaborn as sns
import matplotlib.pyplot as plt
from numpy import median

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

sns.barplot(
    data=tips,
    x="day", y="tip", hue="sex",
    estimator=median,                # usar la mediana en vez de media
    errorbar=None,                   # sin banda de error
    dodge=True
)
plt.title("Mediana de propina por día y sexo (sin errorbars)")
plt.show()
Gráfico de barras por subgrupo

C) Orden y orientación

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
titanic = sns.load_dataset("titanic").dropna(subset=["class", "fare"])

orden = ["Third", "Second", "First"]
sns.barplot(
    data=titanic, y="class", x="fare",
    order=orden, orient="h", errorbar="sd"
)
plt.title("Tarifa promedio por clase (horizontal)")
plt.xlabel("Fare promedio")
plt.ylabel("Clase")
plt.show()
Notas: errorbar admite "sd", "se", ("pi", 95), None, etc. Para proporciones, considerá countplot (frecuencias) o calcula previamente tu métrica y usa barplot.
Gráfico de barras con orden y orientación

4.2 Diagramas de cajas — boxplot

Resumen robusto de la distribución por categoría: mediana, cuartiles y outliers.

A) Boxplot básico

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

sns.boxplot(data=tips, x="day", y="total_bill")
plt.title("Distribución de total_bill por día (boxplot)")
plt.xlabel("Día")
            plt.ylabel("Total de la cuenta (USD)")
plt.show()
Boxplot básico

B) Boxplot por subgrupo (hue) y control de ancho/orden

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

orden = ["Thur", "Fri", "Sat", "Sun"]
sns.boxplot(
    data=tips,
    x="day", y="tip", hue="sex",
    order=orden,
    width=0.6
)
            plt.title("Propina por día y sexo")
plt.show()
Boxplot por subgrupo

C) Boxplot horizontal (útil cuando hay muchas categorías)

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
titanic = sns.load_dataset("titanic").dropna(subset=["class", "fare"])

sns.boxplot(data=titanic, y="class", x="fare", orient="h")
plt.title("Distribución de tarifas por clase (horizontal)")
plt.xlabel("Fare")
plt.ylabel("Clase")
plt.show()
Consejo: si hay muchos outliers, el boxplot puede quedar “aplastado”. Probá violinplot o muestra también estadísticas numéricas.
Boxplot horizontal

4.3 Diagramas de violín — violinplot

Muestran la densidad de la distribución por categoría (similar a un KDE “simétrico”) junto con la mediana/cuartiles opcionalmente.

A) Violín básico

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

sns.violinplot(data=tips, x="day", y="total_bill", inner="quartile")
            plt.title("Distribución (densidad) por día (violin + cuartiles)")
plt.show()
Violinplot básico

B) Violín por subgrupo y ajuste de suavizado

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

sns.violinplot(
    data=tips,
    x="day", y="tip", hue="sex",
    split=True,         # violín “partido” por hue
    inner="quartile",
    bw_adjust=0.8       # suavizado (menor → más detalle)
)
            plt.title("Violinplot partido por sexo (bw_adjust=0.8)")
plt.show()
Violinplot por subgrupo

C) Recortar colas y horizontal

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
titanic = sns.load_dataset("titanic").dropna(subset=["class", "fare"])

sns.violinplot(
    data=titanic, y="class", x="fare",
    cut=0, orient="h"      # cut=0 evita que la KDE se extienda más allá del rango
)
plt.title("Violinplot horizontal de tarifas por clase (cut=0)")
plt.show()
Notas: inner: "box", "quartile", "point" o None. split=True funciona cuando hue tiene dos categorías.
Violinplot horizontal con cut=0

4.4 Diagramas de enjambre — swarmplot

Muestran cada punto (observación) evitando solapamiento con un algoritmo de enjambre. Útil para ver distribución + densidad local sin perder la granularidad.

A) Swarmplot básico

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

sns.swarmplot(data=tips, x="day", y="total_bill", size=5, alpha=0.8)
plt.title("Observaciones individuales por día (swarm)")
plt.show()
Swarmplot básico

B) Swarm por subgrupo y “dodge”

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

sns.swarmplot(
    data=tips,
    x="day", y="tip",
    hue="sex",
    dodge=True,         # separa por subgrupo
    size=5, alpha=0.8
)
plt.title("Swarmplot por día y sexo (dodge=True)")
plt.show()
Swarmplot por subgrupo con dodge

C) Combinar caja/violín + swarm (resumen + granularidad)

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

ax = sns.boxplot(data=tips, x="day", y="total_bill", whis=1.5, width=0.5, fliersize=0)
sns.swarmplot(data=tips, x="day", y="total_bill", color="0.25", size=4, ax=ax)
plt.title("Boxplot + Swarm: resumen + puntos individuales")
plt.show()
Consejos: swarmplot puede ser costoso con miles de puntos. Para muchos datos, usar stripplot (más rápido) o muestras. Ajustá size, alpha y ancho del box/violín para evitar saturación visual.
Boxplot y Swarmplot combinados

4.5 Buenas prácticas y elección del gráfico

  • ¿Promedios con error? → barplot.
  • ¿Distribución robusta + outliers? → boxplot.
  • ¿Forma completa de la distribución (multimodalidad)? → violinplot.
  • ¿Mostrar todas las observaciones? → swarmplot (o stripplot si hay muchas).
  • Comparar subgrupos: usá hue o facetas con catplot(kind="box"/"violin"/"bar"/"swarm").
  • Orden natural: controla order/orient y considera escalas log si hay colas largas.
  • Color y accesibilidad: preferí paletas colorblind-friendly (sns.set_palette("deep") o "colorblind").

4.6 Bonus: catplot (nivel figura)

catplot crea grillas con cualquier gráfico categórico (facetas por filas/columnas).

import seaborn as sns
import matplotlib.pyplot as plt

sns.set_theme(style="whitegrid", context="notebook")
tips = sns.load_dataset("tips")

g = sns.catplot(
    data=tips,
    x="day", y="total_bill",
    hue="sex",
    col="time",            # Lunch vs Dinner en columnas
    kind="violin",         # 'bar' | 'box' | 'violin' | 'swarm' | 'strip' | 'boxen'
    split=False,
    height=3.5, aspect=1
)
g.set_axis_labels("Día", "Total de la cuenta")
g.set_titles("{col_name}")
plt.suptitle("Violinplots por momento del día y sexo", y=1.03)
plt.show()
Catplot con facetas