| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- import pandas as pd
- import matplotlib.pyplot as plt
- import matplotlib.gridspec as gridspec
- import numpy as np
- import warnings
- warnings.filterwarnings('ignore')
- # ── Leer datos ──────────────────────────────────────────────────────────────
- df = pd.read_csv(
- 'resultados1.txt',
- sep=r'\s+',
- decimal=',',
- header=0
- )
- # Variables de interés
- inputs = ['H', 'b', 'tf', 'tw', 'e', 'L']
- outputs = ['Flecha_Media', 'Peso']
- # Convertir a numérico por si acaso
- for col in inputs + outputs:
- df[col] = pd.to_numeric(df[col], errors='coerce')
- df.dropna(subset=inputs + outputs, inplace=True)
- print(f"Filas cargadas: {len(df)}")
- print(df[inputs + outputs].describe().to_string())
- # ── Paleta de colores ────────────────────────────────────────────────────────
- COLORS = {
- 'H': '#E63946',
- 'b': '#457B9D',
- 'tf': '#2A9D8F',
- 'tw': '#E9C46A',
- 'e': '#F4A261',
- 'L': '#A8DADC',
- }
- BG = '#0F1117'
- GRID = '#2A2D3A'
- TEXT = '#E8EAF6'
- plt.rcParams.update({
- 'figure.facecolor': BG,
- 'axes.facecolor': BG,
- 'axes.edgecolor': GRID,
- 'axes.labelcolor': TEXT,
- 'xtick.color': TEXT,
- 'ytick.color': TEXT,
- 'grid.color': GRID,
- 'text.color': TEXT,
- 'font.family': 'monospace',
- })
- labels = {
- 'H': 'H (altura)',
- 'b': 'b (ancho)',
- 'tf': 'tf (ala)',
- 'tw': 'tw (alma)',
- 'e': 'e (excentr.)',
- 'L': 'L (longitud)',
- }
- # ════════════════════════════════════════════════════════════════════════════
- # FIGURA 1 – Scatter: cada entrada vs Flecha_Media y Peso
- # ════════════════════════════════════════════════════════════════════════════
- fig1, axes = plt.subplots(
- 2, 6, figsize=(22, 8),
- facecolor=BG,
- gridspec_kw={'hspace': 0.45, 'wspace': 0.35}
- )
- fig1.suptitle('Entradas vs Salidas · Scatter', fontsize=15, fontweight='bold',
- color=TEXT, y=1.01)
- for col_idx, inp in enumerate(inputs):
- for row_idx, out in enumerate(outputs):
- ax = axes[row_idx, col_idx]
- color = COLORS[inp]
- # Muestreo para no saturar
- sample = df[[inp, out]].dropna().sample(min(2000, len(df)), random_state=42)
- ax.scatter(sample[inp], sample[out],
- s=6, alpha=0.35, color=color, linewidths=0)
- # Línea de tendencia
- z = np.polyfit(sample[inp], sample[out], 1)
- p = np.poly1d(z)
- xs = np.linspace(sample[inp].min(), sample[inp].max(), 200)
- ax.plot(xs, p(xs), color='white', lw=1.2, alpha=0.7)
- if out == 'Flecha_Media':
- ax.axhline(-25, color='white', lw=1.2, linestyle='--', alpha=0.85, label='-25')
- ax.legend(fontsize=7, framealpha=0.2, labelcolor=TEXT)
- ax.set_xlabel(labels[inp], fontsize=8)
- ax.set_ylabel(out, fontsize=8)
- ax.grid(True, linestyle='--', alpha=0.3)
- ax.tick_params(labelsize=7)
- fig1.tight_layout()
- fig1.savefig('scatter_entradas_vs_salidas.png',
- dpi=150, bbox_inches='tight', facecolor=BG)
- print("✓ scatter_entradas_vs_salidas.png guardado")
- # ════════════════════════════════════════════════════════════════════════════
- # FIGURA 2 – Distribuciones (histogramas) de entradas + salidas
- # ════════════════════════════════════════════════════════════════════════════
- all_vars = inputs + outputs
- n = len(all_vars)
- fig2, axes2 = plt.subplots(2, 4, figsize=(18, 8), facecolor=BG,
- gridspec_kw={'hspace': 0.5, 'wspace': 0.35})
- fig2.suptitle('Distribución de variables', fontsize=15, fontweight='bold',
- color=TEXT, y=1.01)
- axes2_flat = axes2.flatten()
- for i, var in enumerate(all_vars):
- ax = axes2_flat[i]
- clr = COLORS.get(var, '#90CAF9')
- data = df[var].dropna()
- ax.hist(data, bins=40, color=clr, alpha=0.85, edgecolor='none')
- ax.axvline(data.mean(), color='white', lw=1.4, linestyle='--', label=f'μ={data.mean():.3g}')
- ax.set_title(var, fontsize=10, fontweight='bold', color=clr)
- ax.set_ylabel('Frecuencia', fontsize=8)
- ax.grid(True, linestyle='--', alpha=0.3)
- ax.tick_params(labelsize=7)
- ax.legend(fontsize=7, framealpha=0.2, labelcolor=TEXT)
- # Ocultar último subplot vacío si n < 8
- for j in range(n, len(axes2_flat)):
- axes2_flat[j].set_visible(False)
- fig2.tight_layout()
- fig2.savefig('distribuciones.png',
- dpi=150, bbox_inches='tight', facecolor=BG)
- print("✓ distribuciones.png guardado")
- # ════════════════════════════════════════════════════════════════════════════
- # FIGURA 3 – Correlación: heatmap
- # ════════════════════════════════════════════════════════════════════════════
- corr = df[inputs + outputs].corr()
- fig3, ax3 = plt.subplots(figsize=(9, 7), facecolor=BG)
- fig3.suptitle('Mapa de correlación', fontsize=14, fontweight='bold', color=TEXT)
- cmap = plt.cm.RdYlGn
- im = ax3.imshow(corr.values, cmap=cmap, vmin=-1, vmax=1, aspect='auto')
- plt.colorbar(im, ax=ax3, fraction=0.046, pad=0.04).ax.tick_params(colors=TEXT)
- ticks = list(range(len(corr.columns)))
- ax3.set_xticks(ticks); ax3.set_yticks(ticks)
- ax3.set_xticklabels(corr.columns, rotation=45, ha='right', fontsize=9)
- ax3.set_yticklabels(corr.columns, fontsize=9)
- for i in range(len(corr)):
- for j in range(len(corr)):
- val = corr.values[i, j]
- color_txt = 'black' if abs(val) > 0.5 else TEXT
- ax3.text(j, i, f'{val:.2f}', ha='center', va='center',
- fontsize=8, color=color_txt, fontweight='bold')
- ax3.grid(False)
- fig3.tight_layout()
- fig3.savefig('correlacion_heatmap.png',
- dpi=150, bbox_inches='tight', facecolor=BG)
- print("✓ correlacion_heatmap.png guardado")
- # ════════════════════════════════════════════════════════════════════════════
- # FIGURA 4 – Boxplots de salidas por cuantiles de L
- # ════════════════════════════════════════════════════════════════════════════
- df['L_cat'] = pd.qcut(df['L'], q=5, labels=['L_Q1','L_Q2','L_Q3','L_Q4','L_Q5'])
- fig4, axes4 = plt.subplots(1, 2, figsize=(14, 6), facecolor=BG)
- fig4.suptitle('Distribución de salidas por cuantiles de L', fontsize=14,
- fontweight='bold', color=TEXT)
- palette = ['#E63946','#F4A261','#E9C46A','#2A9D8F','#457B9D']
- for ax_idx, out in enumerate(outputs):
- ax = axes4[ax_idx]
- groups = [df.loc[df['L_cat'] == cat, out].dropna().values
- for cat in df['L_cat'].cat.categories]
- bp = ax.boxplot(groups, patch_artist=True, notch=False,
- medianprops=dict(color='white', lw=2),
- whiskerprops=dict(color=TEXT),
- capprops=dict(color=TEXT),
- flierprops=dict(marker='o', color=TEXT, alpha=0.2, markersize=2))
- for patch, clr in zip(bp['boxes'], palette):
- patch.set_facecolor(clr)
- patch.set_alpha(0.75)
- ax.set_xticklabels(df['L_cat'].cat.categories, rotation=20, fontsize=8)
- ax.set_title(out, fontsize=11, fontweight='bold', color=TEXT)
- ax.set_ylabel(out, fontsize=9)
- ax.grid(True, axis='y', linestyle='--', alpha=0.3)
- fig4.tight_layout()
- fig4.savefig('boxplot_salidas_por_L.png',
- dpi=150, bbox_inches='tight', facecolor=BG)
- print("✓ boxplot_salidas_por_L.png guardado")
- print("\n✅ Todos los gráficos generados correctamente.")
|