0% found this document useful (0 votes)
7 views19 pages

Generador y Predicción de Consumo Energético

The document outlines a comprehensive framework for generating, modeling, and optimizing energy consumption data in La Paz. It includes classes for data generation, advanced differential models, machine learning predictions, and consumption optimization strategies. The framework utilizes various statistical and machine learning techniques to analyze and predict energy consumption patterns across different zones.

Uploaded by

Abril Michelle
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views19 pages

Generador y Predicción de Consumo Energético

The document outlines a comprehensive framework for generating, modeling, and optimizing energy consumption data in La Paz. It includes classes for data generation, advanced differential models, machine learning predictions, and consumption optimization strategies. The framework utilizes various statistical and machine learning techniques to analyze and predict energy consumption patterns across different zones.

Uploaded by

Abril Michelle
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

import numpy as np

import pandas as pd
import [Link] as plt
from [Link] import curve_fit, newton, minimize
from [Link] import odeint, solve_ivp
from [Link] import find_peaks
from datetime import datetime, timedelta
from [Link] import RandomForestRegressor, GradientBoostingRegressor
from [Link] import StandardScaler
from [Link] import mean_squared_error, r2_score, mean_absolute_error
import warnings
[Link]('ignore')

# ============================================================================
# 1. GENERACIÓN DE DATOS AVANZADA CON MÚLTIPLES FACTORES
# ============================================================================

class GeneradorDatosEnergia:
"""Generador avanzado de datos de consumo energético"""

def __init__(self, dias=180):


[Link] = dias
[Link] = ['Miraflores', 'Sopocachi', 'Calacoto', 'San Miguel', 'Centro',
'Achumani', 'Obrajes', 'Irpavi']
self.fecha_inicio = datetime(2024, 1, 1)

def generar_dataset_completo(self):
"""Genera dataset con múltiples factores realistas"""

dias_range = pd.date_range(self.fecha_inicio, periods=[Link], freq='D')


data = []

for zona in [Link]:


config = self._configurar_zona(zona)

for i, fecha in enumerate(dias_range):


consumo = self._calcular_consumo(i, fecha, config)

[Link]({
'fecha': fecha,
'zona': zona,
'consumo_kwh': round(consumo, 1),
'temperatura': self._temperatura(i),
'dia_semana': [Link],
'es_finde': 1 if [Link] >= 5 else 0,
'mes': [Link],
'poblacion': config['poblacion'],
'tipo_zona': config['tipo']
})

df = [Link](data)
df.to_csv("consumo_energia_lapaz_completo.csv", index=False)
print("✓ Dataset completo generado: consumo_energia_lapaz_completo.csv")
print(f" - {len([Link])} zonas, {[Link]} días, {len(df)} registros
totales")
return df

def _configurar_zona(self, zona):


"""Configuración específica por zona"""
configs = {
'Miraflores': {'base': 280, 'tendencia': 1.2, 'poblacion': 85000, 'tipo':
'residencial'},
'Sopocachi': {'base': 320, 'tendencia': 0.8, 'poblacion': 95000, 'tipo':
'comercial'},
'Calacoto': {'base': 350, 'tendencia': 1.5, 'poblacion': 65000, 'tipo':
'residencial_alto'},
'San Miguel': {'base': 240, 'tendencia': 0.5, 'poblacion': 70000, 'tipo':
'residencial'},
'Centro': {'base': 400, 'tendencia': -0.3, 'poblacion': 120000, 'tipo':
'comercial'},
'Achumani': {'base': 300, 'tendencia': 1.0, 'poblacion': 55000, 'tipo':
'residencial_alto'},
'Obrajes': {'base': 290, 'tendencia': 0.9, 'poblacion': 60000, 'tipo':
'residencial'},
'Irpavi': {'base': 260, 'tendencia': 1.3, 'poblacion': 50000, 'tipo':
'residencial'}
}
return [Link](zona, {'base': 250, 'tendencia': 0.5, 'poblacion': 60000,
'tipo': 'residencial'})

def _calcular_consumo(self, i, fecha, config):


"""Cálculo de consumo con múltiples componentes"""
consumo = config['base'] + config['tendencia'] * i
estacion = 25 * [Link](2 * [Link] * i / 365 - [Link]/2)
ciclo_semanal = 20 * [Link](2 * [Link] * i / 7)
pico_laboral = 15 if [Link] < 5 else -10
evento = [Link](40, 100) if [Link]() < 0.05 else 0
ruido = [Link](0, 18)
consumo_total = consumo + estacion + ciclo_semanal + pico_laboral + evento +
ruido
return [Link](consumo_total, 100, 500)

def _temperatura(self, i):


"""Temperatura simulada para La Paz"""
base_temp = 15
variacion = 5 * [Link](2 * [Link] * i / 365)
ruido = [Link](0, 2)
return round(base_temp + variacion + ruido, 1)

# ============================================================================
# 2. MODELOS DIFERENCIALES AVANZADOS
# ============================================================================

class ModeloDiferencialAvanzado:
"""Múltiples modelos de ecuaciones diferenciales"""

def __init__(self, df_zona):


[Link] = df_zona.copy()
[Link]['dias'] = ([Link]['fecha'] - [Link]['fecha'].min()).[Link]
self.ajustar_modelos()

def ajustar_modelos(self):
"""Ajusta múltiples modelos diferenciales"""
dias = [Link]['dias'].values
consumo = [Link]['consumo_kwh'].values
dE = [Link](consumo)
dt = [Link](dias)
E_mid = (consumo[:-1] + consumo[1:]) / 2

A = np.column_stack([np.ones_like(E_mid), E_mid])
params_lineal = [Link](A, dE/dt, rcond=None)[0]
self.a_lin, self.b_lin = params_lineal

def modelo_logistico(params, E):


r, K = params
return r * E * (1 - E/K)

def error_logistico(params):
predicciones = [modelo_logistico(params, E_mid[i]) for i in
range(len(E_mid))]
return [Link](([Link](predicciones) - dE/dt)**2)

resultado = minimize(error_logistico, x0=[0.01, 500], bounds=[(0.001, 1), (300,


1000)])
self.r_log, self.K_log = resultado.x

t_mid = (dias[:-1] + dias[1:]) / 2


try:
params_osc, _ = curve_fit(
lambda t, a, b, c, omega: a + b*E_mid + c*[Link](omega*t),
t_mid, dE/dt, p0=[self.a_lin, self.b_lin, 5, 2*[Link]/7],
maxfev=5000
)
self.a_osc, self.b_osc, self.c_osc, self.omega_osc = params_osc
except:
self.a_osc = self.a_lin
self.b_osc = self.b_lin
self.c_osc = 5
self.omega_osc = 2*[Link]/7

print(f"\n MODELOS DIFERENCIALES AJUSTADOS:")


print(f" 1. Lineal: dE/dt = {self.a_lin:.4f} + {self.b_lin:.6f}*E")
print(f" 2. Logístico: dE/dt = {self.r_log:.4f}*E*(1 - E/{self.K_log:.1f})")
print(f" 3. Oscilatorio: dE/dt = {self.a_osc:.4f} + {self.b_osc:.6f}*E +
{self.c_osc:.2f}*sin({self.omega_osc:.4f}*t)")

def edo_lineal(self, E, t):


return self.a_lin + self.b_lin * E

def edo_logistico(self, E, t):


return self.r_log * E * (1 - E / self.K_log)

def edo_oscilatorio(self, E, t):


return self.a_osc + self.b_osc * E + self.c_osc * [Link](self.omega_osc * t)

def resolver_todos(self, E0, t_final=90):


"""Resuelve con múltiples métodos y modelos"""
t_span = [0, t_final]
t_eval = [Link](0, t_final, t_final + 1)

sol_lineal = solve_ivp(self.edo_lineal, t_span, [E0], t_eval=t_eval,


method='RK45')
sol_logistico = solve_ivp(self.edo_logistico, t_span, [E0], t_eval=t_eval,
method='RK45')
sol_oscilatorio = solve_ivp(self.edo_oscilatorio, t_span, [E0], t_eval=t_eval,
method='RK45')

return {
'tiempo': sol_lineal.t,
'lineal': sol_lineal.y[0],
'logistico': sol_logistico.y[0],
'oscilatorio': sol_oscilatorio.y[0]
}

# ============================================================================
# 3. MACHINE LEARNING PARA PREDICCIÓN
# ============================================================================

class ModeloMLEnergia:
"""Modelos de Machine Learning para predicción"""

def __init__(self, df):


[Link] = [Link]()
self.preparar_datos()

def preparar_datos(self):
"""Prepara features para ML"""
[Link]['dia_año'] = [Link]['fecha'].[Link]
[Link]['semana'] = [Link]['fecha'].[Link]().week
[Link]['dias_desde_inicio'] = ([Link]['fecha'] -
[Link]['fecha'].min()).[Link]

for zona in [Link]['zona'].unique():


mask = [Link]['zona'] == zona
[Link][mask, 'consumo_lag1'] = [Link][mask, 'consumo_kwh'].shift(1)
[Link][mask, 'consumo_lag7'] = [Link][mask, 'consumo_kwh'].shift(7)
[Link][mask, 'consumo_rolling7'] = [Link][mask,
'consumo_kwh'].rolling(7).mean()

[Link] = [Link]()

[Link] = ['dias_desde_inicio', 'temperatura', 'dia_semana', 'es_finde',


'mes', 'dia_año', 'semana', 'poblacion',
'consumo_lag1', 'consumo_lag7', 'consumo_rolling7']

[Link]['tipo_zona_cod'] = [Link]([Link]['tipo_zona']).codes
[Link]('tipo_zona_cod')

def entrenar_modelos(self, zona, test_size=0.2):


"""Entrena múltiples modelos ML"""
df_zona = [Link][[Link]['zona'] == zona].copy()

n_test = int(len(df_zona) * test_size)


train = df_zona.iloc[:-n_test]
test = df_zona.iloc[-n_test:]

X_train = train[[Link]]
y_train = train['consumo_kwh']
X_test = test[[Link]]
y_test = test['consumo_kwh']

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = [Link](X_test)

rf_model = RandomForestRegressor(n_estimators=100, max_depth=10, random_state=42)


rf_model.fit(X_train_scaled, y_train)
rf_pred = rf_model.predict(X_test_scaled)

gb_model = GradientBoostingRegressor(n_estimators=100, max_depth=5,


random_state=42)
gb_model.fit(X_train_scaled, y_train)
gb_pred = gb_model.predict(X_test_scaled)

print(f"\n MODELOS MACHINE LEARNING - {zona}:")


print(f"\n Random Forest:")
print(f" MAE: {mean_absolute_error(y_test, rf_pred):.2f} kWh")
print(f" RMSE: {[Link](mean_squared_error(y_test, rf_pred)):.2f} kWh")
print(f" R²: {r2_score(y_test, rf_pred):.4f}")

print(f"\n Gradient Boosting:")


print(f" MAE: {mean_absolute_error(y_test, gb_pred):.2f} kWh")
print(f" RMSE: {[Link](mean_squared_error(y_test, gb_pred)):.2f} kWh")
print(f" R²: {r2_score(y_test, gb_pred):.4f}")

importancias = [Link]({
'feature': [Link],
'importance': rf_model.feature_importances_
}).sort_values('importance', ascending=False)

print(f"\n Top 5 Features más importantes:")


for idx, row in [Link](5).iterrows():
print(f" {row['feature']}: {row['importance']:.4f}")

return {
'rf_model': rf_model,
'gb_model': gb_model,
'scaler': scaler,
'test_data': test,
'rf_pred': rf_pred,
'gb_pred': gb_pred,
'importancias': importancias
}

# ============================================================================
# 4. OPTIMIZACIÓN Y CONTROL
# ============================================================================

class OptimizadorConsumo:
"""Optimización del consumo energético"""

def __init__(self, df_zona):


[Link] = df_zona
self.consumo_actual = df_zona['consumo_kwh'].mean()

def optimizar_consumo(self, objetivo_reduccion=0.15, umbral_critico=350):


"""Encuentra estrategia óptima de reducción"""
print(f"\n OPTIMIZACIÓN DE CONSUMO:")
print(f" Consumo actual promedio: {self.consumo_actual:.1f} kWh")
print(f" Objetivo de reducción: {objetivo_reduccion*100:.0f}%")
print(f" Meta: {self.consumo_actual * (1-objetivo_reduccion):.1f} kWh")

estrategias = {
'Eficiencia iluminación': {'reduccion': 0.08, 'costo': 5000},
'Aislamiento térmico': {'reduccion': 0.12, 'costo': 15000},
'Sistemas HVAC eficientes': {'reduccion': 0.15, 'costo': 25000},
'Paneles solares': {'reduccion': 0.25, 'costo': 50000},
'Sensores inteligentes': {'reduccion': 0.10, 'costo': 8000},
'Educación usuarios': {'reduccion': 0.05, 'costo': 2000}
}

def objetivo(x):
reduccion_total = sum(x[i] * list([Link]())[i]['reduccion']
for i in range(len(x)))
costo_total = sum(x[i] * list([Link]())[i]['costo']
for i in range(len(x)))
penalizacion = 1000 * max(0, objetivo_reduccion - reduccion_total)**2
return costo_total - 100000 * reduccion_total + penalizacion

from [Link] import differential_evolution

bounds = [(0, 1)] * len(estrategias)


resultado = differential_evolution(objetivo, bounds, seed=42, maxiter=100)

solucion = (resultado.x > 0.5).astype(int)

print(f"\n ESTRATEGIAS RECOMENDADAS:")


reduccion_final = 0
costo_final = 0

for i, (nombre, datos) in enumerate([Link]()):


if solucion[i]:
print(f" ✓ {nombre}")
print(f" - Reducción: {datos['reduccion']*100:.0f}%")
print(f" - Costo: Bs. {datos['costo']:,}")
reduccion_final += datos['reduccion']
costo_final += datos['costo']

consumo_proyectado = self.consumo_actual * (1 - reduccion_final)


ahorro_anual = (self.consumo_actual - consumo_proyectado) * 365 * 1.2

print(f"\n RESULTADOS:")
print(f" Reducción total: {reduccion_final*100:.1f}%")
print(f" Consumo proyectado: {consumo_proyectado:.1f} kWh/día")
print(f" Inversión total: Bs. {costo_final:,}")
print(f" Ahorro anual estimado: Bs. {ahorro_anual:,.0f}")
print(f" ROI (años): {costo_final/ahorro_anual:.2f}")

if consumo_proyectado < umbral_critico:


print(f" ✅ Se mantiene por debajo del umbral crítico ({umbral_critico}
kWh)")
else:
print(f" Aún supera el umbral crítico ({umbral_critico} kWh)")
return solucion, reduccion_final, costo_final

# ============================================================================
# 5. ANÁLISIS DE PICOS Y ANOMALÍAS
# ============================================================================

def detectar_anomalias(df_zona):
"""Detecta picos y anomalías en el consumo"""
consumo = df_zona['consumo_kwh'].values

media = [Link](consumo)
std = [Link](consumo)
z_scores = [Link]((consumo - media) / std)
anomalias_zscore = z_scores > 2.5

Q1 = [Link](consumo, 25)
Q3 = [Link](consumo, 75)
IQR = Q3 - Q1
limite_inf = Q1 - 1.5 * IQR
limite_sup = Q3 + 1.5 * IQR
anomalias_iqr = (consumo < limite_inf) | (consumo > limite_sup)

picos, propiedades = find_peaks(consumo, height=media + 1.5*std, distance=5)

print(f"\n DETECCIÓN DE ANOMALÍAS:")


print(f" Anomalías Z-score (>2.5σ): {[Link](anomalias_zscore)}")
print(f" Anomalías IQR: {[Link](anomalias_iqr)}")
print(f" Picos detectados: {len(picos)}")

if len(picos) > 0:
print(f"\n PICOS CRÍTICOS:")
for i, pico_idx in enumerate(picos[:5]):
fecha = df_zona.iloc[pico_idx]['fecha']
valor = consumo[pico_idx]
print(f" {i+1}. {[Link]('%Y-%m-%d')}: {valor:.1f} kWh")

return {
'anomalias_zscore': anomalias_zscore,
'anomalias_iqr': anomalias_iqr,
'picos': picos,
'limite_superior': limite_sup
}

# ============================================================================
# 6. FUNCIÓN AUXILIAR PARA AGREGAR EXPLICACIONES
# ============================================================================

def agregar_explicacion_cuadro(fig, objetivo, aplicar, implementar, mejorar):


"""Agrega un cuadro de texto explicativo en la parte inferior de la figura"""
texto = (
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━\n"
f" ANÁLISIS Y RECOMENDACIONES\n"
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━\n\n"
f" OBJETIVO:\n {objetivo}\n\n"
f" APLICAR:\n {aplicar}\n\n"
f" IMPLEMENTAR:\n {implementar}\n\n"
f" MEJORAR:\n {mejorar}\n"
f"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━"
)

props = dict(boxstyle='round', facecolor='#FFF8DC', alpha=0.9, edgecolor='#8B4513',


linewidth=2)
[Link](0.5, 0.02, texto, transform=[Link], fontsize=10,
verticalalignment='bottom', horizontalalignment='center', bbox=props,
family='monospace', wrap=True)

# ============================================================================
# 7. VISUALIZACIONES INDIVIDUALES (MODIFICADAS PARA MOSTRAR SECUENCIALMENTE)
# ============================================================================

def grafica_1_predicciones_edo(df_zona, modelos_edo, zona):


"""Gráfica 1: Predicciones con Ecuaciones Diferenciales"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

[Link](df_zona['fecha'], df_zona['consumo_kwh'], 'o-',


label='Datos reales', alpha=0.6, markersize=4, color='blue', linewidth=2)

fechas_pred = pd.date_range(df_zona['fecha'].max(),
periods=len(modelos_edo['tiempo']), freq='D')
[Link](fechas_pred, modelos_edo['lineal'], '-', label='Modelo Lineal', linewidth=3)
[Link](fechas_pred, modelos_edo['logistico'], '-', label='Modelo Logístico',
linewidth=3)
[Link](fechas_pred, modelos_edo['oscilatorio'], '--', label='Modelo Oscilatorio',
linewidth=3)

[Link](y=350, color='red', linestyle='--', label='Umbral crítico (350 kWh)',


linewidth=2.5)
ax.set_title(f'GRÁFICA 1: PREDICCIONES CON ECUACIONES DIFERENCIALES - {zona}',
fontweight='bold', fontsize=16, pad=20)
ax.set_xlabel('Fecha', fontweight='bold', fontsize=13)
ax.set_ylabel('Consumo (kWh)', fontweight='bold', fontsize=13)
[Link](loc='best', fontsize=11, framealpha=0.9)
[Link](True, alpha=0.3, linestyle='--')

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link](f'grafica_01_predicciones_edo_{zona}.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_2_precision_ml(resultados_ml, zona):


"""Gráfica 2: Precisión de Modelos ML"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)
test_data = resultados_ml['test_data']
[Link](test_data['fecha'], test_data['consumo_kwh'], 'o-',
label='Consumo Real', linewidth=3, markersize=7, color='darkgreen')
[Link](test_data['fecha'], resultados_ml['rf_pred'], 's-',
label='Random Forest', linewidth=2.5, alpha=0.8, markersize=6)
[Link](test_data['fecha'], resultados_ml['gb_pred'], '^-',
label='Gradient Boosting', linewidth=2.5, alpha=0.8, markersize=6)

ax.set_title(f'GRÁFICA 2: PRECISIÓN DE MODELOS DE MACHINE LEARNING - {zona}',


fontweight='bold', fontsize=16, pad=20)
ax.set_xlabel('Fecha', fontweight='bold', fontsize=13)
ax.set_ylabel('Consumo (kWh)', fontweight='bold', fontsize=13)
[Link](fontsize=11, framealpha=0.9)
[Link](True, alpha=0.3, linestyle='--')
ax.tick_params(axis='x', rotation=30)

mae_rf = mean_absolute_error(test_data['consumo_kwh'], resultados_ml['rf_pred'])


r2_rf = r2_score(test_data['consumo_kwh'], resultados_ml['rf_pred'])

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link](f'grafica_02_precision_ml_{zona}.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_3_importancia_features(resultados_ml, zona):


"""Gráfica 3: Importancia de Variables"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

top_features = resultados_ml['importancias'].head(10)
colores = [Link]([Link](0.3, 0.9, len(top_features)))
bars = [Link](top_features['feature'], top_features['importance'], color=colores,
edgecolor='black', linewidth=1.5)

ax.set_title(f'GRÁFICA 3: FACTORES MÁS INFLUYENTES EN EL CONSUMO - {zona}',


fontweight='bold', fontsize=16, pad=20)
ax.set_xlabel('Importancia Relativa', fontweight='bold', fontsize=13)
ax.set_ylabel('Variable', fontweight='bold', fontsize=13)
[Link](True, alpha=0.3, axis='x', linestyle='--')

for i, bar in enumerate(bars):


width = bar.get_width()
[Link](width + 0.005, bar.get_y() + bar.get_height()/2,
f'{width:.4f}', ha='left', va='center', fontsize=10, fontweight='bold')

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link](f'grafica_03_importancia_features_{zona}.png', dpi=200,
bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)
def grafica_4_distribucion_estadistica(df_zona, anomalias, zona):
"""Gráfica 4: Distribución Estadística"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

umbral_critico = 350
n, bins, patches = [Link](df_zona['consumo_kwh'], bins=35, color='lightblue',
edgecolor='black', alpha=0.7, linewidth=1.5)

for i, patch in enumerate(patches):


if bins[i] >= umbral_critico:
patch.set_facecolor('red')
patch.set_alpha(0.8)
elif bins[i] >= umbral_critico * 0.85:
patch.set_facecolor('orange')
patch.set_alpha(0.7)

[Link](x=umbral_critico, color='red', linestyle='--', linewidth=3,


label=f'Umbral crítico ({umbral_critico} kWh)')
[Link](x=df_zona['consumo_kwh'].mean(), color='green',
linestyle='--', linewidth=3, label=f'Promedio
({df_zona["consumo_kwh"].mean():.1f} kWh)')
[Link](x=anomalias['limite_superior'], color='orange',
linestyle='--', linewidth=3, label=f'Límite anomalía
({anomalias["limite_superior"]:.1f} kWh)')

ax.set_title(f'GRÁFICA 4: DISTRIBUCIÓN ESTADÍSTICA DEL CONSUMO - {zona}',


fontweight='bold', fontsize=16, pad=20)
ax.set_xlabel('Consumo (kWh)', fontweight='bold', fontsize=13)
ax.set_ylabel('Frecuencia (días)', fontweight='bold', fontsize=13)
[Link](fontsize=11, framealpha=0.9)
[Link](True, alpha=0.3, axis='y', linestyle='--')

pct_sobre_umbral = (df_zona['consumo_kwh'] > umbral_critico).mean() * 100

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link](f'grafica_04_distribucion_{zona}.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_5_temperatura_consumo(df_zona, zona):


"""Gráfica 5: Relación Temperatura-Consumo"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

scatter = [Link](df_zona['temperatura'], df_zona['consumo_kwh'],


alpha=0.6, c=df_zona['dia_semana'], cmap='viridis',
s=80, edgecolors='black', linewidth=0.8)
z = [Link](df_zona['temperatura'], df_zona['consumo_kwh'], 1)
p = np.poly1d(z)
[Link](df_zona['temperatura'], p(df_zona['temperatura']),
"r--", linewidth=4, label=f'Tendencia: y = {z[0]:.2f}x + {z[1]:.1f}')

ax.set_title(f'GRÁFICA 5: RELACIÓN TEMPERATURA-CONSUMO - {zona}',


fontweight='bold', fontsize=16, pad=20)
ax.set_xlabel('Temperatura (°C)', fontweight='bold', fontsize=13)
ax.set_ylabel('Consumo (kWh)', fontweight='bold', fontsize=13)
[Link](fontsize=11, framealpha=0.9)
[Link](True, alpha=0.3, linestyle='--')

cbar = [Link](scatter, ax=ax)


cbar.set_label('Día de la semana', fontweight='bold', fontsize=12)

corr_temp = df_zona[['temperatura', 'consumo_kwh']].corr().iloc[0, 1]

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link](f'grafica_05_temperatura_{zona}.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_6_patron_semanal(df_zona, zona):


"""Gráfica 6: Patrón Semanal"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

consumo_por_dia = df_zona.groupby('dia_semana')['consumo_kwh'].agg(['mean', 'std',


'count'])
dias_nombres = ['Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado',
'Domingo']
colores_dias = ['#3498db']*5 + ['#e74c3c', '#e74c3c']

bars = [Link](range(7), consumo_por_dia['mean'], yerr=consumo_por_dia['std'],


color=colores_dias, alpha=0.8, capsize=8, edgecolor='black',
linewidth=2,
error_kw={'linewidth': 2, 'ecolor': 'black'})
ax.set_xticks(range(7))
ax.set_xticklabels(dias_nombres, fontweight='bold', fontsize=12)
ax.set_title(f'GRÁFICA 6: COMPORTAMIENTO SEMANAL DEL CONSUMO - {zona}',
fontweight='bold', fontsize=16, pad=20)
ax.set_ylabel('Consumo promedio (kWh)', fontweight='bold', fontsize=13)
[Link](True, alpha=0.3, axis='y', linestyle='--')

for i, bar in enumerate(bars):


height = bar.get_height()
[Link](bar.get_x() + bar.get_width()/2., height +
consumo_por_dia.iloc[i]['std'],
f'{height:.1f}', ha='center', va='bottom', fontweight='bold',
fontsize=11)

dif_finde = consumo_por_dia.loc[5:6, 'mean'].mean() - consumo_por_dia.loc[0:4,


'mean'].mean()
plt.tight_layout(rect=[0, 0.18, 1, 0.98])
[Link](f'grafica_06_patron_semanal_{zona}.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_7_deteccion_anomalias(df_zona, anomalias, zona):


"""Gráfica 7: Detección de Anomalías"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

[Link](range(len(df_zona)), df_zona['consumo_kwh'].values,
'b-', alpha=0.5, linewidth=2, label='Consumo histórico')
[Link](anomalias['picos'], df_zona['consumo_kwh'].values[anomalias['picos']],
'ro', markersize=15, label=f"{len(anomalias['picos'])} picos detectados",
markeredgecolor='darkred', markeredgewidth=2.5)
[Link](y=anomalias['limite_superior'], color='orange',
linestyle='--', linewidth=3, label=f'Límite anomalía IQR
({anomalias["limite_superior"]:.1f} kWh)')
[Link](y=df_zona['consumo_kwh'].mean(), color='green',
linestyle='--', linewidth=2.5, alpha=0.7, label=f'Promedio
({df_zona["consumo_kwh"].mean():.1f} kWh)')
ax.fill_between(range(len(df_zona)),
df_zona['consumo_kwh'].mean() - df_zona['consumo_kwh'].std(),
df_zona['consumo_kwh'].mean() + df_zona['consumo_kwh'].std(),
alpha=0.2, color='green', label='±1σ (rango normal)')

ax.set_title(f'GRÁFICA 7: DETECCIÓN AUTOMÁTICA DE ANOMALÍAS Y PICOS - {zona}',


fontweight='bold', fontsize=16, pad=20)
ax.set_xlabel('Día (índice temporal)', fontweight='bold', fontsize=13)
ax.set_ylabel('Consumo (kWh)', fontweight='bold', fontsize=13)
[Link](loc='best', fontsize=11, framealpha=0.9)
[Link](True, alpha=0.3, linestyle='--')

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link](f'grafica_07_anomalias_{zona}.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_8_tendencia_temporal(df_zona, zona):


"""Gráfica 8: Tendencia Temporal"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

df_zona_temp = df_zona.copy()
df_zona_temp['ma7'] = df_zona_temp['consumo_kwh'].rolling(window=7,
center=True).mean()
df_zona_temp['ma30'] = df_zona_temp['consumo_kwh'].rolling(window=30,
center=True).mean()

[Link](df_zona_temp['fecha'], df_zona_temp['consumo_kwh'],
'o', alpha=0.3, markersize=4, color='gray', label='Datos diarios (ruido)')
[Link](df_zona_temp['fecha'], df_zona_temp['ma7'],
'-', linewidth=3, color='blue', label='Promedio móvil 7 días')
[Link](df_zona_temp['fecha'], df_zona_temp['ma30'],
'-', linewidth=4, color='red', label='Promedio móvil 30 días (tendencia)')
[Link](y=350, color='darkred', linestyle='--', linewidth=3, label='Umbral
crítico')

ax.set_title(f'GRÁFICA 8: TENDENCIA TEMPORAL Y ESTACIONALIDAD - {zona}',


fontweight='bold', fontsize=16, pad=20)
ax.set_xlabel('Fecha', fontweight='bold', fontsize=13)
ax.set_ylabel('Consumo (kWh)', fontweight='bold', fontsize=13)
[Link](loc='best', fontsize=11, framealpha=0.9)
[Link](True, alpha=0.3, linestyle='--')
ax.tick_params(axis='x', rotation=30)

tendencia_mensual = (df_zona_temp['ma30'].iloc[-1] -
df_zona_temp['ma30'].dropna().iloc[0]) / df_zona_temp['ma30'].dropna().iloc[0] * 100

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link](f'grafica_08_tendencia_{zona}.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

# ============================================================================
# 8. VISUALIZACIONES COMPARATIVAS INDIVIDUALES (MODIFICADAS)
# ============================================================================

def grafica_comp_1_ranking_consumo(df, metricas):


"""Gráfica Comparativa 1: Ranking de Zonas"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

metricas_sorted = metricas.sort_values('Promedio', ascending=False)


umbral = 350
colors = ['#c0392b' if x > umbral*0.9 else '#e67e22' if x > umbral*0.7 else
'#27ae60'
for x in metricas_sorted['Promedio']]
bars = [Link](metricas_sorted.index, metricas_sorted['Promedio'],
color=colors, alpha=0.8, edgecolor='black', linewidth=2)
[Link](x=umbral, color='red', linestyle='--', linewidth=4, label='Umbral
crítico')

ax.set_xlabel('Consumo Promedio (kWh)', fontweight='bold', fontsize=13)


ax.set_title('GRÁFICA COMPARATIVA 1: RANKING DE ZONAS POR CONSUMO',
fontweight='bold', fontsize=16, pad=20)
[Link](fontsize=12, framealpha=0.9)
[Link](True, alpha=0.3, axis='x', linestyle='--')

for i, (idx, bar) in enumerate(zip(metricas_sorted.index, bars)):


width = bar.get_width()
[Link](width + 5, bar.get_y() + bar.get_height()/2,
f'{width:.1f}', ha='left', va='center', fontweight='bold', fontsize=11)
plt.tight_layout(rect=[0, 0.18, 1, 0.98])
[Link]('grafica_comp_01_ranking.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_comp_2_evolucion_zonas(df):
"""Gráfica Comparativa 2: Evolución Temporal"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

umbral = 350
for zona in df['zona'].unique():
df_zona = df[df['zona'] == zona]
df_zona_weekly =
df_zona.groupby(df_zona['fecha'].dt.to_period('W'))['consumo_kwh'].mean()
[Link](df_zona_weekly.index.to_timestamp(), df_zona_weekly.values,
marker='o', label=zona, linewidth=2.5, markersize=5, alpha=0.8)

[Link](y=umbral, color='red', linestyle='--', linewidth=3, alpha=0.7,


label='Umbral crítico')
ax.set_xlabel('Semana', fontweight='bold', fontsize=13)
ax.set_ylabel('Consumo Promedio Semanal (kWh)', fontweight='bold', fontsize=13)
ax.set_title('GRÁFICA COMPARATIVA 2: EVOLUCIÓN TEMPORAL DE TODAS LAS ZONAS',
fontweight='bold', fontsize=16, pad=20)
[Link](loc='best', ncol=3, fontsize=10, framealpha=0.9)
[Link](True, alpha=0.3, linestyle='--')
ax.tick_params(axis='x', rotation=45)

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link]('grafica_comp_02_evolucion.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_comp_3_per_capita(metricas):
"""Gráfica Comparativa 3: Consumo Per Cápita"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

metricas_sorted_pc = metricas.sort_values('Consumo_per_capita', ascending=False)


colors_pc = [Link].RdYlGn_r([Link](0.2, 0.8, len(metricas_sorted_pc)))
bars = [Link](range(len(metricas_sorted_pc)),
metricas_sorted_pc['Consumo_per_capita'],
color=colors_pc, alpha=0.8, edgecolor='black', linewidth=2)
ax.set_xticks(range(len(metricas_sorted_pc)))
ax.set_xticklabels(metricas_sorted_pc.index, rotation=45, ha='right',
fontweight='bold', fontsize=12)
ax.set_ylabel('kWh por 1000 habitantes/año', fontweight='bold', fontsize=13)
ax.set_title('GRÁFICA COMPARATIVA 3: EFICIENCIA POBLACIONAL (CONSUMO PER CÁPITA)',
fontweight='bold', fontsize=16, pad=20)
[Link](True, alpha=0.3, axis='y', linestyle='--')

for bar in bars:


height = bar.get_height()
[Link](bar.get_x() + bar.get_width()/2., height,
f'{height:.1f}', ha='center', va='bottom', fontweight='bold',
fontsize=10)

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link]('grafica_comp_03_per_capita.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_comp_4_variabilidad(df, metricas):


"""Gráfica Comparativa 4: Variabilidad por Zona"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

zonas_ordenadas = metricas.sort_values('Promedio', ascending=False).index


datos_box = [df[df['zona'] == zona]['consumo_kwh'].values for zona in
zonas_ordenadas]
bp = [Link](datos_box, labels=zonas_ordenadas, patch_artist=True,
medianprops=dict(color='red', linewidth=3),
boxprops=dict(facecolor='lightblue', alpha=0.7, linewidth=1.5),
whiskerprops=dict(linewidth=2),
capprops=dict(linewidth=2),
flierprops=dict(marker='o', markerfacecolor='red', markersize=8,
alpha=0.6))

[Link](y=350, color='red', linestyle='--', linewidth=3, label='Umbral crítico')


ax.set_xticklabels(zonas_ordenadas, rotation=45, ha='right', fontweight='bold',
fontsize=12)
ax.set_ylabel('Consumo (kWh)', fontweight='bold', fontsize=13)
ax.set_title('GRÁFICA COMPARATIVA 4: VARIABILIDAD Y DISPERSIÓN POR ZONA (BOXPLOT)',
fontweight='bold', fontsize=16, pad=20)
[Link](fontsize=12, framealpha=0.9)
[Link](True, alpha=0.3, axis='y', linestyle='--')

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link]('grafica_comp_04_variabilidad.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_comp_5_correlacion(df, metricas):


"""Gráfica Comparativa 5: Matriz de Correlación"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

zonas_para_corr = [Link](6).index
matriz_consumo = df[df['zona'].isin(zonas_para_corr)].pivot_table(
values='consumo_kwh', index='fecha', columns='zona'
)
corr_matrix = matriz_consumo.corr()

im = [Link](corr_matrix, cmap='coolwarm', aspect='auto', vmin=-1, vmax=1)


ax.set_xticks(range(len(corr_matrix)))
ax.set_yticks(range(len(corr_matrix)))
ax.set_xticklabels(corr_matrix.columns, rotation=45, ha='right', fontsize=11,
fontweight='bold')
ax.set_yticklabels(corr_matrix.columns, fontsize=11, fontweight='bold')
ax.set_title('GRÁFICA COMPARATIVA 5: MATRIZ DE CORRELACIÓN ENTRE ZONAS',
fontweight='bold', fontsize=16, pad=20)

for i in range(len(corr_matrix)):
for j in range(len(corr_matrix)):
text = [Link](j, i, f'{corr_matrix.iloc[i, j]:.2f}',
ha="center", va="center", color="black", fontsize=10,
fontweight='bold')

cbar = [Link](im, ax=ax)


cbar.set_label('Coeficiente de correlación de Pearson', fontweight='bold',
fontsize=12)

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link]('grafica_comp_05_correlacion.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

def grafica_comp_6_score_desempeno(metricas):
"""Gráfica Comparativa 6: Score de Desempeño"""
fig = [Link](figsize=(16, 10))
ax = [Link](111)

metricas_temp = [Link]()
metricas_temp['score_eficiencia'] = 100 - (metricas_temp['Promedio'] -
metricas_temp['Promedio'].min()) / (metricas_temp['Promedio'].max() -
metricas_temp['Promedio'].min()) * 50
metricas_temp['score_estabilidad'] = 100 - (metricas_temp['[Link]'] -
metricas_temp['[Link]'].min()) / (metricas_temp['[Link]'].max() -
metricas_temp['[Link]'].min()) * 50
metricas_temp['Score_Total'] = (metricas_temp['score_eficiencia'] +
metricas_temp['score_estabilidad']) / 2

metricas_sorted_score = metricas_temp.sort_values('Score_Total', ascending=True)


colors_score = ['#27ae60' if x > 70 else '#f39c12' if x > 50 else '#c0392b'
for x in metricas_sorted_score['Score_Total']]
bars = [Link](metricas_sorted_score.index, metricas_sorted_score['Score_Total'],
color=colors_score, alpha=0.8, edgecolor='black', linewidth=2)
[Link](x=70, color='green', linestyle='--', linewidth=2.5, alpha=0.7,
label='Excelente (>70)')
[Link](x=50, color='orange', linestyle='--', linewidth=2.5, alpha=0.7,
label='Aceptable (>50)')
ax.set_xlabel('Score Total (0-100)', fontweight='bold', fontsize=13)
ax.set_title('GRÁFICA COMPARATIVA 6: RANKING INTEGRADO DE DESEMPEÑO ENERGÉTICO',
fontweight='bold', fontsize=16, pad=20)
[Link](fontsize=11, framealpha=0.9)
[Link](True, alpha=0.3, axis='x', linestyle='--')

medallas = [' ', ' ', ' '] + [' ']*(len(metricas_sorted_score)-3)


for i, (idx, bar, medalla) in enumerate(zip(metricas_sorted_score.index, bars,
medallas[::-1])):
width = bar.get_width()
[Link](width + 2, bar.get_y() + bar.get_height()/2,
f'{medalla} {width:.1f}', ha='left', va='center', fontweight='bold',
fontsize=11)

plt.tight_layout(rect=[0, 0.18, 1, 0.98])


[Link]('grafica_comp_06_score.png', dpi=200, bbox_inches='tight')

# MOSTRAR SIN BLOQUEAR


[Link](block=False)
[Link](2)

# ============================================================================
# 9. PROGRAMA PRINCIPAL CON CONTROL INTERACTIVO
# ============================================================================

def ejecutar_analisis_completo():
"""Función principal que ejecuta todo el análisis con control interactivo"""

print("\n" + "="*80)
print("⚡ SISTEMA AVANZADO DE ANÁLISIS ENERGÉTICO - LA PAZ, BOLIVIA")
print(" VERSIÓN CON GRÁFICAS SECUENCIALES")
print("="*80)

# 1. Generar dataset
print("\n[PASO 1/9] Generando dataset completo...")
generador = GeneradorDatosEnergia(dias=180)
df = generador.generar_dataset_completo()

# 2. Seleccionar zona para análisis detallado


zona_analisis = "Miraflores"
df_zona = df[df["zona"] == zona_analisis].copy()
print(f"\n[PASO 2/9] Zona seleccionada para análisis detallado: {zona_analisis}")

# 3. Modelos diferenciales
print(f"\n[PASO 3/9] Ajustando modelos diferenciales...")
modelo_dif = ModeloDiferencialAvanzado(df_zona)
modelos_edo = modelo_dif.resolver_todos(E0=df_zona["consumo_kwh"].iloc[-1])

# 4. Machine Learning
print(f"\n[PASO 4/9] Entrenando modelos de Machine Learning...")
modelo_ml = ModeloMLEnergia(df)
resultados_ml = modelo_ml.entrenar_modelos(zona_analisis)

# 5. Detección de anomalías
print(f"\n[PASO 5/9] Detectando anomalías y picos...")
anomalias = detectar_anomalias(df_zona)

# 6. Optimización
print(f"\n[PASO 6/9] Optimizando estrategias de consumo...")
optimizador = OptimizadorConsumo(df_zona)
optimizador.optimizar_consumo()

# 7. Calcular métricas comparativas


print(f"\n[PASO 7/9] Calculando métricas comparativas entre zonas...")
metricas = [Link]('zona').agg({
'consumo_kwh': ['mean', 'max', 'std', 'min'],
'poblacion': 'first'
}).round(2)
[Link] = ['Promedio', 'Máximo', '[Link]', 'Mínimo', 'Población']
metricas['Consumo_per_capita'] = (metricas['Promedio'] * 365 / metricas['Población']
* 1000).round(2)

# 8. Generar gráficas individuales de la zona con control interactivo


print(f"\n[PASO 8/9] Generando 8 gráficas individuales para {zona_analisis}...")

graficas_individuales = [
("Predicciones con Ecuaciones Diferenciales",
lambda: grafica_1_predicciones_edo(df_zona, modelos_edo, zona_analisis)),
("Precisión de Modelos ML",
lambda: grafica_2_precision_ml(resultados_ml, zona_analisis)),
("Importancia de Variables Predictivas",
lambda: grafica_3_importancia_features(resultados_ml, zona_analisis)),
("Distribución Estadística del Consumo",
lambda: grafica_4_distribucion_estadistica(df_zona, anomalias, zona_analisis)),
("Relación Temperatura-Consumo",
lambda: grafica_5_temperatura_consumo(df_zona, zona_analisis)),
("Patrón Semanal de Consumo",
lambda: grafica_6_patron_semanal(df_zona, zona_analisis)),
("Detección de Anomalías y Picos",
lambda: grafica_7_deteccion_anomalias(df_zona, anomalias, zona_analisis)),
("Tendencia Temporal y Estacionalidad",
lambda: grafica_8_tendencia_temporal(df_zona, zona_analisis))
]

for i, (nombre, funcion) in enumerate(graficas_individuales, 1):


print(f"\n Gráfica {i}: {nombre}")
input(" Presiona Enter para mostrar esta gráfica...")
funcion()
[Link](0.5) # Pequeña pausa para asegurar que se muestre

# 9. Generar gráficas comparativas con control interactivo


print(f"\n[PASO 9/9] Generando 6 gráficas comparativas entre todas las zonas...")

graficas_comparativas = [
("Ranking de Zonas por Consumo",
lambda: grafica_comp_1_ranking_consumo(df, metricas)),
("Evolución Temporal de Todas las Zonas",
lambda: grafica_comp_2_evolucion_zonas(df)),
("Consumo Per Cápita por Zona",
lambda: grafica_comp_3_per_capita(metricas)),
("Variabilidad y Dispersión por Zona",
lambda: grafica_comp_4_variabilidad(df, metricas)),
("Matriz de Correlación entre Zonas",
lambda: grafica_comp_5_correlacion(df, metricas)),
("Ranking Integrado de Desempeño Energético",
lambda: grafica_comp_6_score_desempeno(metricas))
]

for i, (nombre, funcion) in enumerate(graficas_comparativas, 1):


print(f"\n Gráfica Comparativa {i}: {nombre}")
input(" Presiona Enter para mostrar esta gráfica...")
funcion()
[Link](0.5)

# Resumen final
print(f"\n" + "="*80)
print("✅ ANÁLISIS COMPLETADO EXITOSAMENTE")
print("="*80)
print(f"\n Archivos generados:")
print(f"\n DATASET:")
print(f" • consumo_energia_lapaz_completo.csv")
print(f"\n GRÁFICAS INDIVIDUALES ({zona_analisis}):")
for i in range(1, 9):
print(f" • grafica_{i:02d}_*.png")
print(f"\n GRÁFICAS COMPARATIVAS (todas las zonas):")
for i in range(1, 7):
print(f" • grafica_comp_{i:02d}_*.png")

print(f"\n Características del sistema:")


print(f" ✓ 8 gráficas individuales detalladas")
print(f" ✓ 6 gráficas comparativas entre zonas")
print(f" ✓ Control interactivo para ver cada gráfica")
print(f" ✓ Explicaciones detalladas en cada visualización")
print(f" ✓ Archivos PNG guardados automáticamente")

input(f"\n Presiona Enter para finalizar y cerrar todas las ventanas...")


[Link]('all')
print("¡Análisis finalizado! Todas las gráficas han sido guardadas.")

if __name__ == "__main__":
ejecutar_analisis_completo()

You might also like