lección 3
Seaborn y los graficos estadisticos del analista
Los cuatro graficos que usas antes de presentar nada: histograma, boxplot, scatter y heatmap. Seaborn los hace en una linea para que explores rapido y decidas que investigar.
⏱ 50 min
Matplotlib te da control total: puedes mover cada etiqueta, cada linea, cada pixel. Pero ese control tiene un coste. Hacer un histograma con densidad superpuesta, un boxplot comparando cinco grupos, o un heatmap de correlaciones te cuesta entre diez y veinte lineas de codigo cada vez. Seaborn resuelve ese tradeoff: una sola linea donde matplotlib necesita diez, con decisiones estadisticas ya tomadas por defecto. Es el mismo compromiso que en cocina: hacerlo todo desde cero te da libertad absoluta, usar una receta semi-preparada te da velocidad. Y cuando estas explorando datos — intentando entender que pasa antes de presentar nada — la velocidad gana.
Seaborn no sustituye a matplotlib. Se monta encima, como un piloto automatico sobre los mandos manuales. Todo lo que genera seaborn ES un objeto de matplotlib, y puedes retocarlo despues con las mismas herramientas que aprendiste antes (ax.set_title, ax.spines, fig.savefig). La diferencia es el punto de partida: donde matplotlib te da un lienzo en blanco y dice "dibuja lo que quieras", seaborn te da un grafico estadistico completo y dice "retoca lo que no te guste". Para exploracion — el momento en que TU quieres entender los datos, no en que se los presentas a otros — esa diferencia vale oro.
### Explorar vs presentar: dos momentos, dos herramientas
Un analisis tiene dos fases visuales. La primera es privada: tu frente al dato, intentando entender que pasa. Generas diez graficos, tiras ocho, te quedas con dos que revelan algo. La segunda es publica: eliges el grafico que mejor cuenta la historia y lo pules para que un director lo entienda en diez segundos. Seaborn es la herramienta de la primera fase. Matplotlib puro (con todo su control de ejes, colores, anotaciones) es la herramienta de la segunda. Mezclar las dos fases es el error mas comun: o pierdes una hora puliendo un grafico que vas a tirar, o presentas un histograma sin titulo ni etiquetas porque "ya me lo entiendo yo".
Consejo de senior: cuando explores, no pierdas ni un segundo en titulos ni en colores. Genera el grafico, miralo, decide si te dice algo. Si la respuesta es "no", borralo y prueba otro. Si la respuesta es "si, aqui hay algo", entonces y solo entonces abres matplotlib y lo pules para la reunion. He visto juniors perder una hora formateando un scatter plot que al final no aporta nada.
### Instalacion y primer contacto
Seaborn se instala con pip, igual que cualquier libreria. La convencion es importarla como sns — las iniciales de Samuel Norman Seaborn, un personaje de la serie "El Ala Oeste" que le gustaba a Waskom. No es intuitivo, pero es universal: en cualquier tutorial, curso o empresa, sns significa seaborn.
1# Instalacion (una sola vez, en tu entorno virtual)2# pip install seaborn34import seaborn as sns5import matplotlib.pyplot as plt6import pandas as pd78# seaborn trabaja directamente con DataFrames de pandas.9# Esa es una de sus ventajas: le pasas la columna por nombre,10# no tienes que extraerla como lista.
La convencion sns es universal: no la cambies
### Grafico 1: Histograma + KDE — la forma de tus datos
La primera pregunta que te haces con una columna numerica es: como se reparte. No la media, no la suma — la forma. Si los tiempos de respuesta de tu web tienen una campana centrada en 200ms con una cola larga a la derecha, eso te dice que la mayoria de usuarios va bien, pero hay un grupo que sufre. Si los importes de pedido se concentran en dos picos (uno en 15 EUR y otro en 45 EUR), puede que tengas dos segmentos de cliente distintos. El histograma te cuenta esa historia de un vistazo.
Ya viste la distribucion como concepto en estadistica. Ahora vas a verla con codigo. Un histograma divide el rango de la variable en intervalos (bins, barras) y cuenta cuantos valores caen en cada uno. El KDE (Kernel Density Estimation, estimacion de densidad por nucleo) es la curva suave que aproxima esa forma sin el "escalonado" de las barras. Juntos, te dan la mejor foto de una sola variable.
1import seaborn as sns2import matplotlib.pyplot as plt3import pandas as pd45# Datos inline: tiempos de carga de una web (milisegundos)6tiempos = pd.DataFrame({7 'ms': [120, 135, 142, 155, 160, 162, 170, 175, 180, 185,8 190, 195, 200, 205, 210, 215, 220, 230, 250, 280,9 310, 350, 420, 480, 510, 550, 620, 780, 950, 1200]10})1112fig, ax = plt.subplots(figsize=(8, 5))13sns.histplot(data=tiempos, x='ms', kde=True, bins=12,14 color='#a3e635', edgecolor='#1f291c', ax=ax)1516ax.set_title('Distribucion de tiempos de carga')17ax.set_xlabel('Milisegundos')18ax.set_ylabel('Frecuencia')19ax.axvline(x=500, color='#f59e0b', linestyle='--', label='Umbral SLA (500ms)')20ax.legend()21plt.tight_layout()22plt.savefig('histograma_tiempos.png', dpi=150)23plt.close()
Un histograma con KDE revela la cola larga: la mayoria va bien, pero hay usuarios sufriendo
Que te dice este grafico: la mayoria de cargas estan entre 120 y 250ms (bien), pero hay una cola que se estira hasta 1200ms. Esos son los usuarios que se van. Un promedio de 300ms parece aceptable — pero el histograma te dice que ese promedio esconde dos mundos distintos. Exactamente la leccion de "la media que miente" que viste en estadistica, ahora con un solo vistazo.
### Grafico 2: Boxplot — dispersiones y outliers de un vistazo
El boxplot (diagrama de caja y bigotes) es el grafico que responde: hay valores raros que arrastran la media, y cuanto se dispersan los datos. Es como una radiografia de cinco numeros: el minimo real, el primer cuartil (Q1, percentil 25), la mediana (Q2, percentil 50), el tercer cuartil (Q3, percentil 75) y el maximo real. Los puntos que caen fuera de los "bigotes" son los outliers, los valores atipicos.
El IQR (Interquartile Range, rango intercuartilico) es la anchura de la caja: Q3 menos Q1. Los bigotes se extienden hasta 1.5 veces ese IQR por cada lado. Todo lo que cae fuera es un outlier — no necesariamente un error, pero si un valor que merece investigacion. Si ves un boxplot con muchos puntos por encima del bigote superior, tienes una cola derecha pesada: pocos valores muy altos estan arrastrando tu media hacia arriba.
1import seaborn as sns2import matplotlib.pyplot as plt3import pandas as pd45# Datos inline: importe de pedidos por canal6pedidos = pd.DataFrame({7 'importe': [12, 15, 18, 20, 22, 25, 28, 30, 32, 35,8 38, 40, 42, 45, 48, 50, 55, 60, 65, 70,9 85, 120, 250, 15, 18, 22, 25, 30, 35, 40,10 42, 45, 50, 55, 58, 60, 62, 65, 68, 72,11 75, 80, 90, 95, 100, 110, 130, 160, 200, 350],12 'canal': ['web']*23 + ['app']*2713})1415fig, ax = plt.subplots(figsize=(8, 5))16sns.boxplot(data=pedidos, x='canal', y='importe', hue='canal',17 palette={'web': '#a3e635', 'app': '#22d3ee'},18 legend=False, ax=ax)1920ax.set_title('Importe de pedido por canal: app tiene outliers mas extremos')21ax.set_ylabel('Importe (EUR)')22ax.set_xlabel('')23plt.tight_layout()24plt.savefig('boxplot_canales.png', dpi=150)25plt.close()
Comparar dos boxplots lado a lado revela si un grupo tiene mas dispersion que otro
Un outlier no es un error. Es un valor que merece una pregunta. Antes de eliminarlo, investiga: es un pedido real de un cliente corporativo? Es un dato mal introducido? Es un caso de fraude? El boxplot te dice "mira esto"; tu decides que hacer despues. El peor habito de un analista junior es borrar outliers sin preguntar por que estan ahi.
### Grafico 3: Scatter plot — relacion entre dos variables
El scatter plot (grafico de dispersion) responde una pregunta distinta: cuando una variable sube, la otra tambien sube? Es decir: hay correlacion? Ya viste en estadistica que correlacion no implica causalidad. Pero ANTES de preguntarte si hay causa, necesitas ver si hay patron. El scatter es el primer paso: pones una variable en X, otra en Y, y miras si los puntos forman algo parecido a una linea, una nube, o una forma rara.
Seaborn anade un extra: puede superponer una linea de regresion con su intervalo de confianza (la banda sombreada que dice "si la relacion es lineal, los datos estarian mas o menos aqui"). Eso lo hace sns.regplot o sns.lmplot. Pero cuidado: que seaborn te pinte una linea no significa que la relacion sea lineal ni que sea real. La linea es una herramienta visual, no una prueba estadistica.
1import seaborn as sns2import matplotlib.pyplot as plt3import pandas as pd45# Datos inline: horas de soporte al mes vs satisfaccion del cliente6soporte = pd.DataFrame({7 'horas_soporte': [0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6,8 7, 8, 1, 1.5, 2, 2.5, 3, 4, 5, 6,9 0.5, 1, 3, 4, 5, 7, 8, 9, 10, 12],10 'satisfaccion': [9.1, 8.8, 8.5, 8.2, 7.9, 7.5, 7.2, 6.8, 6.2, 5.5,11 5.0, 4.5, 9.0, 8.6, 8.0, 7.8, 7.3, 6.5, 5.8, 5.2,12 9.2, 8.9, 7.4, 6.9, 6.0, 5.1, 4.8, 4.2, 3.8, 3.5]13})1415fig, ax = plt.subplots(figsize=(8, 5))16sns.scatterplot(data=soporte, x='horas_soporte', y='satisfaccion',17 color='#22d3ee', s=80, alpha=0.7, ax=ax)1819# Linea de tendencia para visualizar la direccion20sns.regplot(data=soporte, x='horas_soporte', y='satisfaccion',21 scatter=False, color='#f59e0b', ax=ax)2223ax.set_title('Mas horas de soporte = menor satisfaccion (correlacion negativa)')24ax.set_xlabel('Horas de soporte / mes')25ax.set_ylabel('Satisfaccion (1-10)')26plt.tight_layout()27plt.savefig('scatter_soporte.png', dpi=150)28plt.close()
El scatter revela una relacion negativa clara: a mas soporte necesitado, menos contento esta el cliente
Consejo de senior: un scatter con muchos puntos se vuelve un manchurron ilegible. Si tienes mas de 500 puntos, usa alpha=0.3 para ver donde se concentra la masa, o sns.jointplot(kind="hex") que agrupa puntos en celdas hexagonales con color por densidad. Si tienes mas de 10.000, el scatter ya no es tu herramienta: necesitas un heatmap de densidad o un muestreo.
### Grafico 4: Heatmap de correlacion — la vision panoramica
El scatter te dice si DOS variables estan relacionadas. Pero cuando tienes un DataFrame con diez columnas numericas, hacer un scatter de cada par son 45 combinaciones. Necesitas una vista de pajaro que te diga: cuales son los pares interesantes. Eso es el heatmap de correlacion: una tabla coloreada donde cada celda muestra el coeficiente de correlacion entre dos variables (de -1 a +1), y el color te dice de un vistazo donde hay relaciones fuertes.
1import seaborn as sns2import matplotlib.pyplot as plt3import pandas as pd4import numpy as np56# Datos inline: metricas de una app de suscripcion7np.random.seed(42)8n = 509datos = pd.DataFrame({10 'sesiones_semana': np.random.poisson(5, n),11 'minutos_sesion': np.random.normal(12, 4, n).clip(1),12 'funciones_usadas': np.random.poisson(8, n),13 'dias_desde_registro': np.random.randint(30, 365, n),14 'tickets_soporte': np.random.poisson(1.5, n),15 'nps': np.random.normal(7, 1.5, n).clip(1, 10).round(1),16})17# Crear correlacion artificial para el ejemplo18datos['minutos_sesion'] = datos['sesiones_semana'] * 2 + np.random.normal(0, 2, n)19datos['nps'] = (10 - datos['tickets_soporte'] * 1.2 + np.random.normal(0, 1, n)).clip(1, 10)2021corr = datos.corr()2223fig, ax = plt.subplots(figsize=(8, 6))24sns.heatmap(corr, annot=True, fmt='.2f', cmap='coolwarm',25 center=0, vmin=-1, vmax=1,26 linewidths=0.5, linecolor='#1f291c', ax=ax)2728ax.set_title('Mapa de correlaciones: donde estan las relaciones fuertes?')29plt.tight_layout()30plt.savefig('heatmap_correlacion.png', dpi=150)31plt.close()
El heatmap de correlacion te dice donde mirar: las celdas con color intenso son las relaciones que merecen un scatter
El heatmap es un mapa del tesoro: te dice donde cavar. Si ves que nps y tickets_soporte tienen correlacion -0.90, eso te dice "ve a hacer un scatter de esos dos y confirma la relacion". No hagas 45 scatter plots a ciegas: deja que el heatmap te diga cuales merecen la pena.
### Cuando usar cada grafico: el mapa rapido
### Seaborn vs matplotlib: cuando uso cada uno
La pregunta no es cual es mejor — es cual es mejor para ESTE momento. Seaborn brilla cuando estas explorando: quieres ver muchos graficos rapido, la estetica por defecto ya es decente, y no necesitas controlar cada pixel. Matplotlib brilla cuando presentas: quieres un titulo con el mensaje exacto, colores corporativos, anotaciones que guien el ojo del director, y cada elemento colocado donde tu decides. En la practica, un analisis empieza con seaborn y termina con matplotlib. Y muchas veces, el grafico final es un hibrido: empiezas con seaborn y luego retocas el axes con metodos de matplotlib.
- Seaborn -- Explorar distribuciones, comparar grupos, ver correlaciones. Una linea de codigo por grafico. Poca personalizacion necesaria. Output: tu cuaderno de notas.
- Matplotlib -- Presentar un hallazgo concreto. Control total sobre cada pixel. Titulo que dice la conclusion, no la metrica. Anotaciones, colores corporativos. Output: la reunion del lunes.
- Ambos juntos -- El patron mas profesional: sns.histplot(..., ax=ax) genera el grafico base, y despues ax.set_title() / ax.axvline() / ax.legend() lo retoca para la presentacion. Es posible porque seaborn devuelve objetos de matplotlib.
1import seaborn as sns2import matplotlib.pyplot as plt3import pandas as pd45# El patron hibrido: seaborn genera, matplotlib retoca6tiempos = pd.DataFrame({7 'ms': [120, 135, 142, 155, 160, 170, 180, 200, 220, 250,8 280, 310, 350, 420, 510, 620, 780, 950, 1200, 190],9 'pagina': ['home']*10 + ['checkout']*1010})1112fig, ax = plt.subplots(figsize=(8, 5))1314# Paso 1: seaborn genera el grafico estadistico15sns.boxplot(data=tiempos, x='pagina', y='ms', hue='pagina',16 palette={'home': '#a3e635', 'checkout': '#f59e0b'},17 legend=False, ax=ax)1819# Paso 2: matplotlib lo retoca para la reunion20ax.set_title('Checkout tarda casi 3x mas que Home — priorizar optimizacion',21 fontsize=13, fontweight='bold')22ax.set_ylabel('Tiempo de carga (ms)')23ax.set_xlabel('')24ax.axhline(y=500, color='#f59e0b', linestyle='--', alpha=0.5)25ax.text(1.3, 510, 'SLA: 500ms', color='#f59e0b', fontsize=9)26ax.spines['top'].set_visible(False)27ax.spines['right'].set_visible(False)2829plt.tight_layout()30plt.savefig('boxplot_presentacion.png', dpi=150)31plt.close()
El patron hibrido: seaborn para la forma, matplotlib para el mensaje. El titulo dice la conclusion, no la metrica.
Consejo de senior: el titulo de un grafico de presentacion nunca es la metrica ("Tiempo de carga por pagina"). El titulo ES la conclusion ("Checkout tarda casi 3x mas que Home — priorizar optimizacion"). Si el director solo lee el titulo — y muchos solo leen el titulo — tiene que entender la decision. La metrica va en los ejes.
### El flujo completo: de los datos crudos al hallazgo
Vamos a juntar los cuatro graficos en una secuencia real. Imagina que te pasan un dataset de clientes de un SaaS y te dicen "el churn (la tasa de baja) ha subido un 3%. Averigua por que". Tu no sabes nada del dato todavia. El flujo de exploracion seria:
- 01.Heatmap de correlacion: que variables se mueven con churn? Ves que "tickets_soporte" y "dias_sin_login" tienen correlacion alta con churn.
- 02.Scatter de las sospechosas: scatter de tickets_soporte vs dias_sin_login, coloreado por churn/no-churn. Confirmas que los que se van estan en la esquina alta-alta.
- 03.Boxplot comparativo: boxplot de tickets_soporte separando churn=si vs churn=no. Confirmas que los que se van tienen mediana 5 tickets/mes vs 1.5 de los que se quedan.
- 04.Histograma del hallazgo: histograma de tickets_soporte solo para los churners. Ves un pico en las semanas 3-4 tras el registro. La cola de soporte se carga a los nuevos.
- 05.Conclusion: el churn no es de precio (la hipotesis del stakeholder). Es de experiencia en las primeras semanas. Los que necesitan mucho soporte al principio se van. La accion: mejorar el onboarding, no bajar el precio.
Fijate en que cada grafico te lleva al siguiente. El heatmap dice "mira aqui". El scatter confirma la direccion. El boxplot cuantifica la diferencia. El histograma encuentra el cuando. No son cuatro graficos sueltos: son cuatro pasos de una investigacion. Y el ultimo paso no es un grafico — es una frase que cambia una decision.
### Errores comunes con graficos estadisticos
- Histograma con demasiados bins -- Si pones 50 barras para 100 datos, cada barra tiene 2 valores y el grafico parece ruido. Regla de oro: empieza con bins=20 y ajusta.
- Confundir correlacion con causalidad en el scatter -- "Los helados causan ahogamientos" porque ambos suben en verano. El scatter muestra co-movimiento, no causa.
- Borrar outliers del boxplot sin investigar -- Un outlier puede ser un error de carga, pero tambien el mejor cliente de la empresa. Antes de tirarlo, pregunta por que esta ahi.
- Heatmap con variables redundantes -- Si metes "ingresos" e "ingresos_netos" (que son la misma cosa menos un porcentaje fijo), la correlacion sera 0.99 y no dice nada util.
- Interpretar un scatter de 20 puntos -- Con menos de 30-50 observaciones, cualquier patron puede ser ruido. No declares correlacion con un punado de puntos.
Regístrate para guardar tu progreso.
## comentarios
Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.
Inicia sesión para comentar y responder.
cargando comentarios...