
Gráficos Avanzados con Matplotlib: Visualizaciones Estadísticas y Complejas
Aprende a crear gráficos avanzados con Matplotlib: histogramas, mapas de calor, diagramas de caja, gráficos polares y visualizaciones estadísticas complejas.
¡Lleva tus visualizaciones al siguiente nivel! En este tutorial aprenderás a crear gráficos avanzados y visualizaciones estadísticas complejas con Matplotlib, incluyendo histogramas, mapas de calor, diagramas de caja, gráficos polares y mucho más.
Objetivo: Dominar las técnicas avanzadas de visualización en Matplotlib para crear gráficos estadísticos, mapas de calor, contornos y visualizaciones especializadas.
Índice
- Histogramas y Distribuciones
- Diagramas de Caja (Box Plots)
- Diagramas de Violín
- Mapas de Calor
- Gráficos de Contorno
- Gráficos Polares
- Barras de Error
- Gráficos de Área Apilada
- Matrices de Dispersión
- Visualizaciones Estadísticas Avanzadas
Histogramas y Distribuciones
Los histogramas son esenciales para visualizar distribuciones de datos.
Histograma Básico
import matplotlib.pyplot as plt
import numpy as np
# Generar datos con distribución normal
np.random.seed(42)
datos = np.random.normal(0, 1, 1000)
plt.figure(figsize=(12, 8))
# Crear histograma
plt.hist(datos, bins=30, alpha=0.7, color='skyblue', edgecolor='black', linewidth=1)
plt.xlabel('Valor', fontsize=12)
plt.ylabel('Frecuencia', fontsize=12)
plt.title('Histograma de Distribución Normal', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3)
# Agregar línea de densidad
from scipy import stats
x_densidad = np.linspace(min(datos), max(datos), 100)
densidad = stats.norm.pdf(x_densidad, np.mean(datos), np.std(datos))
plt.plot(x_densidad, densidad * len(datos) * (max(datos) - min(datos)) / 30,
'r-', linewidth=2, label='Densidad teórica')
plt.legend()
plt.show()
Múltiples Histogramas
import matplotlib.pyplot as plt
import numpy as np
# Generar diferentes distribuciones
np.random.seed(42)
datos1 = np.random.normal(0, 1, 1000)
datos2 = np.random.normal(2, 1.5, 1000)
datos3 = np.random.exponential(1, 1000)
plt.figure(figsize=(15, 10))
# Subplot 1: Histogramas superpuestos
plt.subplot(2, 2, 1)
plt.hist(datos1, bins=30, alpha=0.5, label='Normal(0,1)', color='blue', density=True)
plt.hist(datos2, bins=30, alpha=0.5, label='Normal(2,1.5)', color='red', density=True)
plt.hist(datos3, bins=30, alpha=0.5, label='Exponencial(1)', color='green', density=True)
plt.xlabel('Valor')
plt.ylabel('Densidad')
plt.title('Histogramas Superpuestos')
plt.legend()
plt.grid(True, alpha=0.3)
# Subplot 2: Histogramas apilados
plt.subplot(2, 2, 2)
plt.hist([datos1, datos2, datos3], bins=30, alpha=0.7,
label=['Normal 1', 'Normal 2', 'Exponencial'], stacked=True)
plt.xlabel('Valor')
plt.ylabel('Frecuencia')
plt.title('Histogramas Apilados')
plt.legend()
plt.grid(True, alpha=0.3)
# Subplot 3: Histogramas por grupos
plt.subplot(2, 2, 3)
bins = np.linspace(-3, 6, 30)
plt.hist(datos1, bins=bins, alpha=0.7, label='Grupo A', color='lightblue')
plt.hist(datos2, bins=bins, alpha=0.7, label='Grupo B', color='lightcoral')
plt.xlabel('Valor')
plt.ylabel('Frecuencia')
plt.title('Comparación por Grupos')
plt.legend()
plt.grid(True, alpha=0.3)
# Subplot 4: Histograma 2D
plt.subplot(2, 2, 4)
plt.hist2d(datos1, datos2, bins=30, cmap='viridis', alpha=0.8)
plt.colorbar(label='Frecuencia')
plt.xlabel('Variable X')
plt.ylabel('Variable Y')
plt.title('Histograma 2D')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Histogramas con Estadísticas
import matplotlib.pyplot as plt
import numpy as np
# Datos de ejemplo
np.random.seed(42)
datos = np.random.normal(50, 15, 1000)
plt.figure(figsize=(14, 8))
# Crear histograma
n, bins, patches = plt.hist(datos, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
# Calcular estadísticas
media = np.mean(datos)
mediana = np.median(datos)
desvio = np.std(datos)
q25, q75 = np.percentile(datos, [25, 75])
# Líneas de referencia
plt.axvline(media, color='red', linestyle='--', linewidth=2, label='.1f')
plt.axvline(mediana, color='green', linestyle='--', linewidth=2, label='.1f')
plt.axvline(media + desvio, color='orange', linestyle=':', linewidth=2, label='.1f')
plt.axvline(media - desvio, color='orange', linestyle=':', linewidth=2, label='.1f')
# Relleno para el IQR
plt.axvspan(q25, q75, alpha=0.2, color='yellow', label='.1f')
plt.xlabel('Valor', fontsize=12)
plt.ylabel('Frecuencia', fontsize=12)
plt.title('Histograma con Estadísticas Descriptivas', fontsize=14, fontweight='bold')
plt.legend()
plt.grid(True, alpha=0.3)
# Agregar texto con estadísticas
stats_text = ".1f"".1f"".1f"".1f"".1f"f"""
Estadísticas:
Media: {media:.1f}
Mediana: {mediana:.1f}
Desvío: {desvio:.1f}
Q25: {q25:.1f}
Q75: {q75:.1f}
IQR: {q75-q25:.1f}
"""
plt.text(0.02, 0.98, stats_text, transform=plt.gca().transAxes,
fontsize=10, verticalalignment='top',
bbox=dict(boxstyle='round,pad=0.5', facecolor='lightgray', alpha=0.8))
plt.show()
Fig. 1: Histogramas, box plots y violin plots para análisis estadístico
Diagramas de Caja (Box Plots)
Los diagramas de caja son excelentes para comparar distribuciones y detectar outliers.
Box Plot Básico
import matplotlib.pyplot as plt
import numpy as np
# Generar datos
np.random.seed(42)
datos1 = np.random.normal(50, 10, 200)
datos2 = np.random.normal(60, 15, 200)
datos3 = np.random.normal(45, 8, 200)
plt.figure(figsize=(12, 8))
# Crear box plot
bp = plt.boxplot([datos1, datos2, datos3],
labels=['Grupo A', 'Grupo B', 'Grupo C'],
patch_artist=True,
boxprops=dict(facecolor='lightblue', color='blue'),
medianprops=dict(color='red', linewidth=2),
whiskerprops=dict(color='blue', linewidth=1.5),
capprops=dict(color='blue', linewidth=1.5),
flierprops=dict(marker='o', markerfacecolor='red', markersize=5, alpha=0.6))
plt.ylabel('Valor', fontsize=12)
plt.title('Diagramas de Caja Comparativos', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3, axis='y')
# Agregar valores estadísticos
for i, datos in enumerate([datos1, datos2, datos3], 1):
q1, mediana, q3 = np.percentile(datos, [25, 50, 75])
plt.text(i, mediana, '.1f', ha='center', va='bottom',
fontsize=9, fontweight='bold', color='red')
plt.show()
Box Plots Horizontales y Personalizados
import matplotlib.pyplot as plt
import numpy as np
# Datos de diferentes categorías
categorias = ['Producto A', 'Producto B', 'Producto C', 'Producto D']
datos = [
np.random.normal(100, 20, 100),
np.random.normal(120, 25, 100),
np.random.normal(90, 15, 100),
np.random.normal(110, 30, 100)
]
plt.figure(figsize=(14, 10))
# Box plot horizontal
plt.subplot(2, 1, 1)
bp = plt.boxplot(datos, vert=False, labels=categorias, patch_artist=True)
# Personalizar colores
colores = ['lightblue', 'lightgreen', 'lightcoral', 'lightyellow']
for patch, color in zip(bp['boxes'], colores):
patch.set_facecolor(color)
patch.set_alpha(0.7)
plt.title('Box Plots Horizontales', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3, axis='x')
# Box plot con outliers destacados
plt.subplot(2, 1, 2)
# Agregar algunos outliers extremos
datos_con_outliers = datos.copy()
datos_con_outliers[0] = np.append(datos_con_outliers[0], [200, -10]) # Outliers en Producto A
bp2 = plt.boxplot(datos_con_outliers, labels=categorias, patch_artist=True,
flierprops=dict(marker='o', markerfacecolor='red', markersize=8,
markeredgecolor='black', alpha=0.8))
# Colores para boxes
for patch in bp2['boxes']:
patch.set_facecolor('lightblue')
patch.set_alpha(0.7)
plt.title('Box Plots con Outliers Destacados', fontsize=14, fontweight='bold')
plt.ylabel('Valor', fontsize=12)
plt.grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()
Box Plots Agrupados
import matplotlib.pyplot as plt
import numpy as np
# Datos de múltiples grupos y condiciones
np.random.seed(42)
grupos = ['Control', 'Tratamiento A', 'Tratamiento B']
condiciones = ['Antes', 'Después']
datos = {}
for grupo in grupos:
for condicion in condiciones:
if grupo == 'Control':
base = 50
elif grupo == 'Tratamiento A':
base = 60
else:
base = 55
if condicion == 'Después':
base += np.random.choice([-10, 0, 10, 20])
datos[f'{grupo}_{condicion}'] = np.random.normal(base, 8, 50)
plt.figure(figsize=(14, 8))
# Preparar datos para box plot agrupado
etiquetas = []
datos_plot = []
for grupo in grupos:
for condicion in condiciones:
etiquetas.append(f'{grupo}\n{condicion}')
datos_plot.append(datos[f'{grupo}_{condicion}'])
# Crear box plot agrupado
positions = np.arange(len(etiquetas))
bp = plt.boxplot(datos_plot, positions=positions, widths=0.6, patch_artist=True)
# Colores alternados para grupos
colores = ['lightblue', 'lightblue', 'lightgreen', 'lightgreen', 'lightcoral', 'lightcoral']
for patch, color in zip(bp['boxes'], colores):
patch.set_facecolor(color)
patch.set_alpha(0.7)
# Líneas separadoras entre grupos
for i in [1.5, 3.5]:
plt.axvline(i, color='gray', linestyle='--', alpha=0.5)
plt.xticks(positions, etiquetas, fontsize=10)
plt.ylabel('Puntuación', fontsize=12)
plt.title('Box Plots Agrupados: Efecto de Tratamientos', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3, axis='y')
# Leyenda
plt.legend([plt.Rectangle((0,0),1,1, facecolor='lightblue', alpha=0.7),
plt.Rectangle((0,0),1,1, facecolor='lightgreen', alpha=0.7),
plt.Rectangle((0,0),1,1, facecolor='lightcoral', alpha=0.7)],
['Control', 'Tratamiento A', 'Tratamiento B'],
title='Grupos', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()
Diagramas de Violín
Los diagramas de violín combinan box plots con estimaciones de densidad kernel.
Violin Plot Básico
import matplotlib.pyplot as plt
import numpy as np
# Datos de ejemplo
np.random.seed(42)
datos1 = np.random.normal(50, 10, 200)
datos2 = np.random.normal(60, 15, 200)
datos3 = np.random.normal(45, 8, 200)
plt.figure(figsize=(12, 8))
# Crear violin plot
parts = plt.violinplot([datos1, datos2, datos3],
showmeans=True, showmedians=True, showextrema=True)
# Personalizar colores
for pc in parts['bodies']:
pc.set_facecolor('lightblue')
pc.set_edgecolor('blue')
pc.set_alpha(0.7)
# Personalizar elementos
parts['cmeans'].set_color('red')
parts['cmedians'].set_color('green')
parts['cmins'].set_color('purple')
parts['cmaxes'].set_color('purple')
plt.xticks([1, 2, 3], ['Grupo A', 'Grupo B', 'Grupo C'])
plt.ylabel('Valor', fontsize=12)
plt.title('Diagramas de Violín', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3, axis='y')
# Leyenda
plt.legend([plt.Line2D([0], [0], color='red', linewidth=2),
plt.Line2D([0], [0], color='green', linewidth=2),
plt.Line2D([0], [0], color='purple', linewidth=2)],
['Media', 'Mediana', 'Mín/Máx'],
bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
Violin Plots con Box Plots
import matplotlib.pyplot as plt
import numpy as np
# Datos
np.random.seed(42)
grupos = ['A', 'B', 'C', 'D']
datos = [np.random.normal(i*10 + 50, 5 + i, 100) for i in range(4)]
plt.figure(figsize=(14, 8))
# Crear violin plot
violin_parts = plt.violinplot(datos, positions=range(len(grupos)),
showmeans=True, showmedians=True)
# Personalizar violines
for i, pc in enumerate(violin_parts['bodies']):
pc.set_facecolor(plt.cm.viridis(i / len(grupos)))
pc.set_edgecolor('black')
pc.set_alpha(0.7)
# Agregar box plots encima
box_parts = plt.boxplot(datos, positions=range(len(grupos)),
widths=0.1, patch_artist=True,
boxprops=dict(facecolor='white', alpha=0.8),
medianprops=dict(color='red'))
plt.xticks(range(len(grupos)), grupos)
plt.xlabel('Grupos', fontsize=12)
plt.ylabel('Valor', fontsize=12)
plt.title('Violin Plots con Box Plots Integrados', fontsize=14, fontweight='bold')
plt.grid(True, alpha=0.3, axis='y')
plt.show()
Mapas de Calor
Los mapas de calor son ideales para visualizar matrices de datos y correlaciones.
Heatmap Básico
import matplotlib.pyplot as plt
import numpy as np
# Crear matriz de datos
np.random.seed(42)
datos = np.random.rand(10, 10)
plt.figure(figsize=(10, 8))
# Crear heatmap
im = plt.imshow(datos, cmap='viridis', aspect='auto')
# Agregar barra de colores
cbar = plt.colorbar(im, shrink=0.8, aspect=20)
cbar.set_label('Valor', fontsize=12)
plt.xlabel('Columna', fontsize=12)
plt.ylabel('Fila', fontsize=12)
plt.title('Mapa de Calor Básico', fontsize=14, fontweight='bold')
# Agregar valores en las celdas
for i in range(datos.shape[0]):
for j in range(datos.shape[1]):
plt.text(j, i, '.2f', ha='center', va='center',
fontsize=8, color='white' if datos[i, j] > 0.5 else 'black')
plt.show()
Heatmap de Correlación
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# Simular datos de diferentes variables
np.random.seed(42)
n = 100
datos = {
'Altura': np.random.normal(170, 10, n),
'Peso': np.random.normal(70, 15, n),
'Edad': np.random.normal(30, 8, n),
'Ingresos': np.random.normal(50000, 20000, n),
'Educación': np.random.normal(12, 3, n)
}
df = pd.DataFrame(datos)
# Calcular matriz de correlación
corr_matrix = df.corr()
plt.figure(figsize=(10, 8))
# Crear heatmap de correlación
mask = np.triu(np.ones_like(corr_matrix, dtype=bool)) # Máscara para triángulo superior
im = plt.imshow(corr_matrix, cmap='RdYlBu_r', vmin=-1, vmax=1)
# Agregar valores
for i in range(len(corr_matrix)):
for j in range(len(corr_matrix)):
if not mask[i, j]: # Solo mostrar triángulo inferior
plt.text(j, i, '.2f', ha='center', va='center',
fontsize=10, fontweight='bold',
color='white' if abs(corr_matrix.iloc[i, j]) > 0.5 else 'black')
# Configurar ejes
plt.xticks(range(len(corr_matrix)), corr_matrix.columns, rotation=45, ha='right')
plt.yticks(range(len(corr_matrix)), corr_matrix.index)
# Barra de colores
cbar = plt.colorbar(im, shrink=0.8, aspect=20)
cbar.set_label('Coeficiente de Correlación', fontsize=12)
plt.title('Matriz de Correlación', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()
Heatmap con Anotaciones Personalizadas
import matplotlib.pyplot as plt
import numpy as np
# Crear datos más complejos
np.random.seed(42)
filas = ['Producto A', 'Producto B', 'Producto C', 'Producto D', 'Producto E']
columnas = ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun']
ventas = np.random.randint(100, 1000, (len(filas), len(columnas)))
plt.figure(figsize=(12, 8))
# Crear heatmap
im = plt.imshow(ventas, cmap='YlOrRd', aspect='auto')
# Barra de colores
cbar = plt.colorbar(im, shrink=0.8, aspect=15)
cbar.set_label('Ventas ($)', fontsize=12)
# Configurar ejes
plt.xticks(range(len(columnas)), columnas, fontsize=10)
plt.yticks(range(len(filas)), filas, fontsize=10)
plt.xlabel('Mes', fontsize=12)
plt.ylabel('Producto', fontsize=12)
plt.title('Mapa de Calor de Ventas por Producto y Mes', fontsize=14, fontweight='bold')
# Agregar valores con formato condicional
for i in range(len(filas)):
for j in range(len(columnas)):
valor = ventas[i, j]
color = 'white' if valor > 600 else 'black'
plt.text(j, i, f'${valor}', ha='center', va='center',
fontsize=9, fontweight='bold', color=color)
# Líneas de cuadrícula
plt.grid(False) # Desactivar grid automático
for i in range(len(filas)):
plt.axhline(i - 0.5, color='white', linewidth=1)
for j in range(len(columnas)):
plt.axvline(j - 0.5, color='white', linewidth=1)
plt.tight_layout()
plt.show()
Gráficos de Contorno
Los gráficos de contorno muestran líneas de nivel en datos tridimensionales.
Contorno Básico
import matplotlib.pyplot as plt
import numpy as np
# Crear datos 3D
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(X) * np.cos(Y)
plt.figure(figsize=(15, 10))
# Gráfico de contorno
plt.subplot(2, 2, 1)
cs = plt.contour(X, Y, Z, levels=15, cmap='viridis')
plt.clabel(cs, inline=True, fontsize=8)
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Gráfico de Contorno')
plt.colorbar(cs, shrink=0.8)
plt.grid(True, alpha=0.3)
# Gráfico de contorno relleno
plt.subplot(2, 2, 2)
csf = plt.contourf(X, Y, Z, levels=20, cmap='RdYlBu')
plt.colorbar(csf, shrink=0.8)
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Contorno Relleno')
# Contorno con etiquetas personalizadas
plt.subplot(2, 2, 3)
cs3 = plt.contour(X, Y, Z, levels=np.linspace(-1, 1, 11), colors='black', linewidths=0.5)
plt.clabel(cs3, inline=True, fontsize=8, fmt='%.1f')
plt.contourf(X, Y, Z, levels=np.linspace(-1, 1, 11), cmap='RdYlBu', alpha=0.3)
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Contorno con Etiquetas')
plt.grid(True, alpha=0.3)
# Contorno 3D
from mpl_toolkits.mplot3d import Axes3D
ax = plt.subplot(2, 2, 4, projection='3d')
surf = ax.plot_surface(X, Y, Z, cmap='viridis', alpha=0.8)
ax.contour(X, Y, Z, levels=10, cmap='viridis', offset=-2)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Contorno 3D')
plt.colorbar(surf, ax=ax, shrink=0.6, aspect=10)
plt.tight_layout()
plt.show()
Gráficos Polares
Los gráficos polares son útiles para datos con dirección o ángulo.
Gráfico Polar Básico
import matplotlib.pyplot as plt
import numpy as np
# Datos polares
theta = np.linspace(0, 2*np.pi, 100)
r = 2 * np.sin(4 * theta)
plt.figure(figsize=(12, 8))
# Gráfico polar
ax = plt.subplot(2, 2, 1, polar=True)
ax.plot(theta, r, 'b-', linewidth=2)
ax.set_title('Rosa Polar', fontsize=12, fontweight='bold')
ax.grid(True, alpha=0.3)
# Múltiples funciones polares
ax2 = plt.subplot(2, 2, 2, polar=True)
r1 = 1 + np.cos(theta)
r2 = 1 + 0.5 * np.cos(2*theta)
r3 = 1 + 0.3 * np.cos(3*theta)
ax2.plot(theta, r1, 'r-', label='n=1', linewidth=2)
ax2.plot(theta, r2, 'g-', label='n=2', linewidth=2)
ax2.plot(theta, r3, 'b-', label='n=3', linewidth=2)
ax2.set_title('Funciones Polares', fontsize=12, fontweight='bold')
ax2.legend()
ax2.grid(True, alpha=0.3)
# Datos direccionales (viento)
ax3 = plt.subplot(2, 2, 3, polar=True)
np.random.seed(42)
direcciones = np.random.uniform(0, 2*np.pi, 50)
velocidades = np.random.uniform(0, 10, 50)
ax3.scatter(direcciones, velocidades, c=velocidades, cmap='viridis', s=50, alpha=0.7)
ax3.set_title('Dirección y Velocidad del Viento', fontsize=12, fontweight='bold')
ax3.set_rlabel_position(90)
ax3.grid(True, alpha=0.3)
# Radar chart
ax4 = plt.subplot(2, 2, 4, polar=True)
categorias = ['Fuerza', 'Velocidad', 'Precisión', 'Resistencia', 'Técnica']
valores = [8, 7, 9, 6, 8]
# Cerrar el polígono
angulos = np.linspace(0, 2*np.pi, len(categorias), endpoint=False).tolist()
valores += valores[:1]
angulos += angulos[:1]
ax4.plot(angulos, valores, 'o-', linewidth=2, color='red', markersize=8)
ax4.fill(angulos, valores, alpha=0.25, color='red')
ax4.set_xticks(angulos[:-1])
ax4.set_xticklabels(categorias)
ax4.set_ylim(0, 10)
ax4.set_title('Gráfico Radar', fontsize=12, fontweight='bold')
ax4.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Barras de Error
Las barras de error muestran la incertidumbre en las mediciones.
Barras de Error Básicas
import matplotlib.pyplot as plt
import numpy as np
# Datos con incertidumbre
x = np.arange(5)
y = [2, 3, 1, 4, 2.5]
y_err = [0.2, 0.3, 0.1, 0.4, 0.2] # Error en Y
x_err = [0.1, 0.1, 0.1, 0.1, 0.1] # Error en X
plt.figure(figsize=(12, 8))
# Barras de error en Y
plt.subplot(2, 2, 1)
plt.errorbar(x, y, yerr=y_err, fmt='o-', capsize=5, capthick=2,
elinewidth=2, markersize=8, color='blue')
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Barras de Error en Y')
plt.grid(True, alpha=0.3)
# Barras de error en X e Y
plt.subplot(2, 2, 2)
plt.errorbar(x, y, xerr=x_err, yerr=y_err, fmt='s-', capsize=3,
color='red', ecolor='orange', linewidth=2)
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Barras de Error en X e Y')
plt.grid(True, alpha=0.3)
# Barras de error con diferentes estilos
plt.subplot(2, 2, 3)
plt.errorbar(x, y, yerr=y_err, fmt='o', capsize=5, capthick=1,
elinewidth=1, markersize=6, color='green', alpha=0.7)
plt.errorbar(x, np.array(y) + 1, yerr=y_err, fmt='s', capsize=3,
elinewidth=2, markersize=6, color='purple', alpha=0.7)
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Múltiples Series con Barras de Error')
plt.legend(['Serie 1', 'Serie 2'])
plt.grid(True, alpha=0.3)
# Barras de error en barras verticales
plt.subplot(2, 2, 4)
bars = plt.bar(x, y, yerr=y_err, capsize=5, color='lightblue',
edgecolor='blue', linewidth=1, alpha=0.7)
plt.xlabel('Categoría')
plt.ylabel('Valor')
plt.title('Barras con Error')
plt.grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()
Gráficos de Área Apilada
Los gráficos de área apilada muestran la contribución de diferentes componentes a un total.
Área Apilada Básica
import matplotlib.pyplot as plt
import numpy as np
# Datos de ventas por categoría
meses = np.arange(1, 13)
ventas_A = np.array([120, 150, 180, 200, 250, 300, 280, 320, 350, 380, 400, 420])
ventas_B = np.array([100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, 320])
ventas_C = np.array([80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190])
plt.figure(figsize=(14, 8))
# Gráfico de área apilada
plt.stackplot(meses, ventas_A, ventas_B, ventas_C,
labels=['Producto A', 'Producto B', 'Producto C'],
colors=['lightblue', 'lightgreen', 'lightcoral'],
alpha=0.8)
plt.xlabel('Mes', fontsize=12)
plt.ylabel('Ventas ($)', fontsize=12)
plt.title('Ventas por Producto - Área Apilada', fontsize=14, fontweight='bold')
plt.legend(loc='upper left')
plt.grid(True, alpha=0.3)
# Agregar línea del total
total = ventas_A + ventas_B + ventas_C
plt.plot(meses, total, 'k-', linewidth=2, label='Total')
plt.legend()
plt.xticks(meses, ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun',
'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'], rotation=45)
plt.tight_layout()
plt.show()
Matrices de Dispersión
Las matrices de dispersión muestran relaciones entre múltiples variables.
Scatter Matrix Básica
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Crear datos
np.random.seed(42)
n = 100
datos = {
'Altura': np.random.normal(170, 10, n),
'Peso': np.random.normal(70, 15, n),
'Edad': np.random.normal(30, 8, n),
'Ingresos': np.random.normal(50000, 20000, n)
}
df = pd.DataFrame(datos)
plt.figure(figsize=(12, 12))
# Crear scatter matrix manualmente
variables = list(datos.keys())
n_vars = len(variables)
for i in range(n_vars):
for j in range(n_vars):
plt.subplot(n_vars, n_vars, i*n_vars + j + 1)
if i == j:
# Diagonal: histogramas
plt.hist(df[variables[i]], bins=15, alpha=0.7, color='skyblue', edgecolor='black')
plt.title(f'{variables[i]}', fontsize=10)
else:
# Off-diagonal: scatter plots
plt.scatter(df[variables[j]], df[variables[i]], alpha=0.6, s=20, color='blue')
if i == n_vars-1: # Última fila
plt.xlabel(variables[j], fontsize=8)
if j == 0: # Primera columna
plt.ylabel(variables[i], fontsize=8)
# Ocultar ticks para claridad
if i < n_vars-1:
plt.xticks([])
if j > 0:
plt.yticks([])
plt.suptitle('Matriz de Dispersión', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.show()
Visualizaciones Estadísticas Avanzadas
Gráfico Q-Q (Quantile-Quantile)
import matplotlib.pyplot as plt
import numpy as np
from scipy import stats
# Datos
np.random.seed(42)
datos_normales = np.random.normal(0, 1, 200)
datos_exponenciales = np.random.exponential(1, 200)
plt.figure(figsize=(14, 6))
# Q-Q plot para datos normales
plt.subplot(1, 2, 1)
stats.probplot(datos_normales, dist="norm", plot=plt)
plt.title('Q-Q Plot: Datos Normales vs Normal Teórica')
plt.grid(True, alpha=0.3)
# Q-Q plot para datos exponenciales
plt.subplot(1, 2, 2)
stats.probplot(datos_exponenciales, dist="expon", plot=plt)
plt.title('Q-Q Plot: Datos Exponenciales vs Exponencial Teórica')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
Gráfico de Andrews
import matplotlib.pyplot as plt
import numpy as np
from pandas.plotting import andrews_curves
import pandas as pd
# Crear datos de ejemplo
np.random.seed(42)
n = 50
datos = {
'Grupo': np.random.choice(['A', 'B', 'C'], n),
'Var1': np.random.normal(0, 1, n),
'Var2': np.random.normal(2, 1, n),
'Var3': np.random.normal(-1, 1, n),
'Var4': np.random.normal(1, 2, n)
}
df = pd.DataFrame(datos)
plt.figure(figsize=(12, 8))
# Gráfico de Andrews
andrews_curves(df, 'Grupo', colormap='viridis')
plt.title('Curvas de Andrews por Grupo', fontsize=14, fontweight='bold')
plt.xlabel('t', fontsize=12)
plt.ylabel('f(t)', fontsize=12)
plt.grid(True, alpha=0.3)
plt.legend(title='Grupo')
plt.show()
¡Has dominado los gráficos avanzados de Matplotlib! Ahora puedes crear visualizaciones estadísticas complejas y mapas de calor profesionales.
En el próximo tutorial aprenderás sobre Gráficos 3D para crear visualizaciones tridimensionales impactantes.
No hay comentarios aún
Sé el primero en comentar este tutorial.