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.")