<jupyter_start><jupyter_text>Forecasting Daily Solar Power Generation Using Gaussian Naive Bayes  IntroductionThis project uses dataset "Solar Power Generation Data" from [kaggle](https://www.kaggle.com/anikannal/solar-power-generation-data). The dataset contains two solar power plants in India over a 34 day period. It has two pairs of files - each pair has one power generation dataset and one sensor readings dataset. The power generation datasets are gathered at the inverter level - each inverter has multiple lines of solar panels attached to it. The sensor data is gathered at a plant level - single array of sensors optimally placed at the plant. Datasets- Plant_1_Generation_Data.csv : Solar power generation data such as plant id, time, and amount power - Plant_1_Weather_Sensor_Data.csv : Weather sensor data such as plant id, time, temperature, and irradiation- Plant_2_Generation_Data.csv : Solar power generation data such as plant id, time, and amount power- Plant_2_Weather_Sensor_Data.csv : Weather sensor data such as plant id, time, temperature, and irradiation ProblemCan we predict the power generation for next couple of days? - this allows for better grid management  How Solar Power WorksThis figure shows how solar panel works step by step.  1. Import Libraries and Dataset<jupyter_code>import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime
import datetime as dt

from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()

%matplotlib inline
sns.set_style("darkgrid")
sns.set_palette("Set2")
df_generation1 = pd.read_csv('../datasets/solar-power-generation/Plant_1_Generation_Data.csv')
df_weather1 = pd.read_csv('../datasets/solar-power-generation/Plant_1_Weather_Sensor_Data.csv')
df_generation2 = pd.read_csv('../datasets/solar-power-generation/Plant_2_Generation_Data.csv')
df_weather2 = pd.read_csv('../datasets/solar-power-generation/Plant_2_Weather_Sensor_Data.csv')
df_generation1['DATE_TIME'] = pd.to_datetime(df_generation1['DATE_TIME'], format='%d-%m-%Y %H:%M')
df_generation2['DATE_TIME'] = pd.to_datetime(df_generation2['DATE_TIME'], format='%Y-%m-%d %H:%M')
df_weather1['DATE_TIME'] = pd.to_datetime(df_weather1['DATE_TIME'], format='%Y-%m-%d %H:%M')
df_weather2['DATE_TIME'] = pd.to_datetime(df_weather2['DATE_TIME'], format='%Y-%m-%d %H:%M')<jupyter_output><empty_output><jupyter_text>2. Exploratory Data Analysis  Daily Power Generation<jupyter_code>def groupDailyPower(df_generation):
    df = df_generation.groupby(['DATE_TIME']).sum()
    df = df.sort_index()
    index_date = pd.date_range(start=df.index[0].date(), end=df.index[-1].date())
    df_sort = df.groupby(by=[df.index.year, df.index.month, df.index.day], as_index=False).sum()
    df_sort.index = index_date
    return df_sort 
    
def showDailyPower(plant1, plant2, feature, label1, label2):
    df_sort1 = groupDailyPower(plant1)
    df_sort2 = groupDailyPower(plant2)
    
    plt.figure(figsize=(16, 6))
    plt.title(feature)
    sns.lineplot(x=df_sort1.index, y=feature, data=df_sort1, label=label1)
    sns.lineplot(x=df_sort1.index, y=df_sort1[feature].mean(), label='avg '+label1)
    sns.lineplot(x=df_sort1.index, y=feature, data=df_sort2, label=label2)
    sns.lineplot(x=df_sort1.index, y=df_sort2[feature].mean(), label='avg '+label2)
    
showDailyPower(df_generation1, df_generation2, 'DC_POWER', 'plant1', 'plant2')
showDailyPower(df_generation1, df_generation2, 'AC_POWER', 'plant1', 'plant2')<jupyter_output><empty_output><jupyter_text>The linechart shows that there's a huge different in the amount of DC power between Plant 1 and Plant 2. On the other hand, there's a slight different in AC power both of them.  Daily Power Inverting Efficiency<jupyter_code>def powerEfficiency(df_generation, label):
    df = df_generation.groupby(['DATE_TIME']).sum()
    df = df.sort_index()
    index_date = pd.date_range(start=df.index[0].date(), end=df.index[-1].date())
    df_sort = df.groupby(by=[df.index.year, df.index.month, df.index.day], as_index=False).sum()
    df_sort['efficiency'] = df_sort['AC_POWER']*100/df_sort['DC_POWER']
    df_sort.index = index_date
    
    plt.figure(figsize=(16, 6))
    plt.ylim(df_sort['efficiency'].min()-5, df_sort['efficiency'].max()+5)
    plt.title('efficiency ' + label)
    sns.lineplot(x=df_sort.index, y='efficiency', data=df_sort, label=label)
    
powerEfficiency(df_generation1, 'plant1')
powerEfficiency(df_generation2, 'plant2')<jupyter_output><empty_output><jupyter_text>The average of plant 2's inverter efficiency is about 98% but plant 1 is below 10%.  Daily Weather Condition<jupyter_code>def groupDailyWeather(df_weather, operation):
    df = df_weather.groupby(['DATE_TIME']).last()
    df = df.sort_index()
    index_date = pd.date_range(start=df.index[0].date(), end=df.index[-1].date())
    
    if operation == 'mean':
        df_sort = df.groupby(by=[df.index.year, df.index.month, df.index.day], as_index=False).mean()
    elif operation == 'max':
        df_sort = df.groupby(by=[df.index.year, df.index.month, df.index.day], as_index=False).max()
        
    df_sort.index = index_date
    return df_sort 

def showDailyWeather(weather1, weather2, feature, label1, label2):
    df_sort1_mean = groupDailyWeather(weather1, 'mean')
    df_sort1_max = groupDailyWeather(weather1, 'max')
    df_sort2_mean = groupDailyWeather(weather2, 'mean')
    df_sort2_max = groupDailyWeather(weather2, 'max')
    
    plt.figure(figsize=(16, 6))
    plt.title(feature)
    sns.lineplot(x=df_sort1_mean.index, y=feature, data=df_sort1_mean, label='mean '+label1)
    sns.lineplot(x=df_sort1_mean.index, y=feature, data=df_sort1_max, label='max '+label1)
    sns.lineplot(x=df_sort2_mean.index, y=feature, data=df_sort2_mean, label='mean '+label2, style=1, dashes=[(2,2)])
    sns.lineplot(x=df_sort2_mean.index, y=feature, data=df_sort2_max, label='max '+label2, style=1,  dashes=[(2,2)])
    
showDailyWeather(df_weather1, df_weather2, 'AMBIENT_TEMPERATURE', 'plant1', 'plant2')
showDailyWeather(df_weather1, df_weather2, 'MODULE_TEMPERATURE', 'plant1', 'plant2')
showDailyWeather(df_weather1, df_weather2, 'IRRADIATION', 'plant1', 'plant2')<jupyter_output><empty_output><jupyter_text>The graphs above show the change of environment condition in daily mean and max value. It tells that there's a slight different in ambient temperatures.  2. Build Model To predict model, we can use a simpler model such as Naive Bayes by selecting 10 days in a row as features.<jupyter_code>from sklearn.naive_bayes import GaussianNB
def prepareData(df_sort, feature):
    n_bins = 12
    bins = np.linspace(df_sort[feature].min(), df_sort[feature].max(), n_bins)
    binned = np.digitize(df_sort[feature], bins)
    binned_series = pd.Series(binned, index = df_sort[feature].index)
    
    bin_means = {}
    for binn in range(1,n_bins+1):
        bin_means[binn] = df_sort['AC_POWER'][binned == binn].mean()
        
    lagged_list = []
    for s in range(13):
        lagged_list.append(binned_series.shift(s))

    lagged_frame = pd.concat(lagged_list, 1).dropna()

    train_X = lagged_frame.iloc[:,1:]
    train_y = lagged_frame.iloc[:,0]
    
    return train_X, train_y, bin_means
# Generation 1
df_sort1 = groupDailyPower(df_generation1)
train_X1, train_y1, bin_means1 = prepareData(df_sort1, 'AC_POWER')

# Generation 2
df_sort2 = groupDailyPower(df_generation2)
train_X2, train_y2, bin_means2 = prepareData(df_sort2, 'AC_POWER')
# Generation 1
model1 = GaussianNB()
model1.fit(train_X1, train_y1)

# Generation 2
model2 = GaussianNB()
model2.fit(train_X2, train_y2)<jupyter_output><empty_output><jupyter_text>3. Predict<jupyter_code>def meanFromClass(bin_means, prediction):
    return(bin_means[prediction[0]])

def newPredict(last_y, last_x):
    last = last_y.astype(float)
    new_input = np.concatenate((last, last_x))[:12]
    return new_input

def newIndexDate(days, train_y):
    return pd.date_range(start=train_y.index[0].date(), end=train_y.index[-1].date() + dt.timedelta(days=days))
def prediction(train_X, train_y, model, bin_means, df_sort):
    num_next_days = 12
    pred_insample = model.predict(train_X)

    last = np.array([pred_insample[-1].astype(float)])
    last_X = np.array(train_X)[-1]
    new_input = np.concatenate((last, last_X))[:12]

    result_predict = []
    for i in range(num_next_days):
        result = model1.predict(new_input.reshape(1, -1))
        result_predict.append(result[0])
        new_input = newPredict(result, new_input)

    pred_insample = np.concatenate((pred_insample, np.array(result_predict)))
    new_index = newIndexDate(num_next_days, train_y)

    pred_insample = pd.DataFrame(pred_insample, index = new_index)
    resulting_prediction = pd.Series(np.nan, index = new_index)
    for row in range(len(pred_insample)):
        resulting_prediction.iloc[row] = meanFromClass(bin_means, pred_insample.values[row])

    plt.figure(figsize = (12,6))
    plt.plot(df_sort['AC_POWER'])
    plt.plot(resulting_prediction)
# Generation 1
prediction(train_X1, train_y1, model1, bin_means1, df_sort1)
# Generation 2
prediction(train_X2, train_y2, model2, bin_means2, df_sort2)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12452625879805089, 'fraction_numerical': 0.021007038440714672, 'mean_word_length': 5.378453038674033, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '182916', 'license': 'Apache-2.0', 'n_tokens_mistral': 3356, 'n_tokens_neox': 3217, 'n_words': 682, 'path': 'solar-power-generation/solar-power-generation.ipynb', 'repo_name': 'arifintahu/data-science-projects', 'size': '9235'}