# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: tpot
#     language: python
#     name: tpot
# ---

import os
import math
import pandas as pd
import numpy as np
import seaborn as sns
from pandas import datetime
from matplotlib import pyplot as plt
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import r2_score


# +
## convert one to multiple series
def lag_ahead_series(data, n_in=1, n_out=1, n_vars = 1,dropnan=True):
    df = pd.DataFrame(data)
    cols, names = list(), list()
    # input sequence (t-n, ... t-1)
    for j in range(n_vars):
        for i in range(n_in, 0, -1):
            cols.append(df.iloc[:,j].shift(i))
            names.append('{}{}(t-{})'.format(df.columns[0],j+1, i))
    
    # forecast sequence (t+1, ... t+n)
    for j in range(n_vars):
        for i in range(0, n_out):
            cols.append(df.iloc[:,j].shift(-i))
            names += [('{}{}(t+{})'.format(df.columns[0],j+1, i)) ]
    # put it all together
    agg = pd.concat(cols, axis=1)
    agg.columns = names
    
    #drop rows with NaN values
    if dropnan:
        agg.dropna(inplace=True)
    return agg

## Distribution plot funciton
def distri_plot(df):
    f, axes = plt.subplots(3, 3, figsize=(15, 11), sharex=False)
    for idx, col_name in enumerate(df.columns, 0): 
        idx = int(idx)
        ## jump to plotting energy
        if(col_name == "rain"):
            sns.distplot(df["energy"],ax=axes[2,2])
            return
        sns.distplot(df[col_name],ax=axes[idx//3,idx%3])  
    ## plot     
    plt.tight_layout()

## Scatter plot function
def scatter_plot(df):
    f, axes = plt.subplots(4, 2, figsize=(15, 11), sharex=False)
    for idx, col_name in enumerate(df.columns, 0): 
        idx = int(idx)
        if(idx >= 8):
            return
        ## jump to plotting energy
        sns.scatterplot(x= col_name,y = "energy", data = df, ax=axes[idx//2,idx%2])  
    ## plot     
    plt.tight_layout()


## plot dataframe creation
def plot_df(arr, name):
    plot_df = pd.DataFrame()
    i = 0
    for row in arr:
        plot_df.insert(i, "{}_{}".format(name,i), row, True) 
        i += 1
    return plot_df

def get_eval(y, yhat):
    print("MSE: {}".format(mean_squared_error(y,yhat)))
    print("MAE: {}".format(mean_absolute_error(y,yhat)))
    print("r2_score: {}".format(r2_score(y,yhat, multioutput = "variance_weighted")))

## feature/ target construction fucntion with lag variable
def feature_target_construct(df, load_lag, target_ahead, temp_ahead, wd_on = False):
    tempcols = ['temperature','temperature.1','temperature.2','temperature.3']
    load = df['TotalLoad']
    f_temp = pd.DataFrame()
    for col in tempcols:
        temp = lag_ahead_series(df[col], 
                             n_in = 0,
                             n_out = temp_ahead + 1,
                             n_vars = 1,
                             dropnan = True)
        f_temp = pd.concat([f_temp, temp], axis = 1)
    
    t = lag_ahead_series(load,
                          n_in = 0,
                          n_out = target_ahead + 1,
                          n_vars = 1,
                          dropnan = True)
                  
    if(target_ahead > temp_ahead):
        num_ahead = target_ahead
        f_temp = f_temp.iloc[load_lag:-num_ahead + temp_ahead,:]
        t = t.iloc[load_lag:,:]
    elif(target_ahead < temp_ahead):
        num_ahead = temp_ahead
        f_temp = f_temp.iloc[load_lag:,:]
        t = t.iloc[load_lag:-num_ahead + target_ahead,:]
    else:
        num_ahead = temp_ahead
        f_temp = f_temp.iloc[load_lag:,:]
        t = t.iloc[load_lag:,:]
        
    ## load lag series
    f_load = lag_ahead_series(load,
                          n_in = load_lag,
                          n_out = 0,
                          n_vars = 1,
                          dropnan = True).iloc[:-num_ahead,:]
    
    ## feature concatanation
    if wd_on:
        weekday = pd.get_dummies(df.iloc[load_lag:-num_ahead,-1])
        f = pd.concat([weekday, f_temp, f_load], axis = 1)
    else:
        f = pd.concat([f_temp, f_load], axis = 1)
    
    ## target load values
    
    
    return f, t
# -

train = pd.read_csv("../data/train_elia.csv", index_col= 'time')
test = pd.read_csv("../data/test_elia.csv", index_col= 'time')

#                                   load_lag, target_ahead , temp_ahead, weekday_on
f_train, t_train = feature_target_construct(train, 4, 4, 4, True)

f_test, t_test = feature_target_construct(test, 4, 4, 4, True)

# ### TPOT: 6 hour ahead, 15 mins

# +
from tpot import TPOTRegressor
from mmm import mul_reg_config_dict
from sklearn.model_selection import TimeSeriesSplit
#import mul_config as mc

train_X, val_X, train_y, val_y = train_test_split(f_train, t_train, train_size = 0.1, shuffle = False)

tpot_reg = TPOTRegressor(generations=20, 
                         population_size=60,
                         offspring_size=None, 
                         mutation_rate=0.9,
                         crossover_rate=0.1,
                         scoring='neg_mean_squared_error',
                         cv=TimeSeriesSplit(n_splits = 5),
                         subsample=1.0,
                         n_jobs=4,
                         max_time_mins=None, 
                         max_eval_time_mins=5,
                         random_state=123, 
                         config_dict=mul_reg_config_dict,
                         template=None,
                         warm_start=False,
                         memory=None,
                         use_dask=False,
                         periodic_checkpoint_folder=None,
                         early_stop=None,
                         verbosity=0,
                         disable_update_check=False)

tpot_reg.fit(train_X , train_y)

# -

#val_X, val_y = train.iloc[500:600,:8], ahead_e.iloc[500:600,:]
yhat = tpot_reg.predict(f_test)

# ### Result Evaluation

get_eval(t_test, yhat)

# +
## assignment
real = t_test.to_numpy()
guess = yhat

real = real[1:2,:]
guess = guess[1:2,:]
rpdf = plot_df(real, "observed")
gpdf = plot_df(guess, "prediction")
    
#plot 
ax = plt.gca()
gpdf.plot(figsize=(25,10), colormap = 'plasma',style='--x',legend = True, ax = ax)
rpdf.plot(figsize=(25,10), color = 'g',style ='-o',legend = True, ax = ax, lw = 4)
ax.legend(frameon=False, loc='upper right', ncol=6, prop={'size': 16})

plt.show()
# -

# ### TPOT: 24 hour ahead, half-hourly

# +
from tpot import TPOTRegressor
from tpot_mulr import mul_reg_config_dict
from sklearn.model_selection import train_test_split
#import mul_config as mc

train_X, val_X, train_y, val_y = train_test_split(ahead_w, ahead_e, train_size = 0.05, test_size = 0.95, random_state = 123)

tpot_reg = TPOTRegressor(generations=30, 
                         population_size=60, 
                         n_jobs=4, 
                         verbosity=2, 
                         random_state=123,
                         subsample= 0.8,
                         config_dict=mul_reg_config_dict)
tpot_reg.fit(train_X , train_y)

# -

yhat = tpot_reg.predict(test_X)
mean_squared_error(test_y, yhat)
mean_absolute_error(test_y, yhat)
r2_score(test_y, yhat)

# +
## assignment
real = test_y.to_numpy()
guess = yhat
real = real[50:51,:49]
guess = guess[50:51,:49]
rpdf = plot_df(real, "observed")
gpdf = plot_df(guess, "prediction")
    
#plot 
ax = plt.gca()
gpdf.plot(figsize=(25,10), colormap = 'plasma',style='--',legend = True, ax = ax)
rpdf.plot(figsize=(25,10), color = 'g',style ='-o',legend = True, ax = ax, lw = 4)
ax.legend(frameon=False, loc='upper right', ncol=6, prop={'size': 16})

plt.show()

StarcoderdataJupyterScriptsDedupFiltered