import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense, Dropout
from sklearn.metrics import mean_absolute_percentage_error
# Load the dataset
= pd.read_excel('NR_Demand.xlsx')
data
# Convert 'Date' to datetime object
'Date'] = pd.to_datetime(data['Date'])
data[
# Separate 2023 and 2024 data
= data[data['Date'].dt.year == 2023]
train_data = data[(data['Date'].dt.year == 2024) & (data['Date'].dt.month <= 3)] # January to March 2024
test_data
# Define prediction period (April, May, June 2024)
= pd.date_range(start='2024-04-01', end='2024-06-30', freq='H')
predict_dates
# Preprocess training data (2023)
#train_data['Hour'] = pd.to_datetime(train_data['Start Time'], format='%I:%M %p').dt.hour
#train_data['Hour_sin'] = np.sin(2 * np.pi * train_data['Hour'] / 24)
#train_data['Hour_cos'] = np.cos(2 * np.pi * train_data['Hour'] / 24)
# Map 'Day of the Week' to numerical values
= {'Monday': 0, 'Tuesday': 1, 'Wednesday': 2, 'Thursday': 3, 'Friday': 4, 'Saturday': 5, 'Sunday': 6}
day_of_week_mapping 'Day_of_week_num'] = train_data['Day of the Week'].map(day_of_week_mapping)
train_data['Day_of_week_sin'] = np.sin(2 * np.pi * train_data['Day_of_week_num'] / 7)
train_data['Day_of_week_cos'] = np.cos(2 * np.pi * train_data['Day_of_week_num'] / 7)
train_data[
# Features for LSTM model
= ['Hour_sin', 'Hour_cos', 'Day_of_week_sin', 'Day_of_week_cos', 'Hourly Demand Met (in MW)']
features
# Scale the training data
= MinMaxScaler(feature_range=(0, 1))
scaler 'Hourly Demand Met (in MW)'] = scaler.fit_transform(train_data[['Hourly Demand Met (in MW)']])
train_data[
import warnings
"ignore") warnings.filterwarnings(
# Create sequences for LSTM
def create_sequences(data, time_steps=24):
= []
sequences = []
labels for i in range(len(data) - time_steps):
= data[i:(i + time_steps)]
seq_data = data[i + time_steps]
seq_label
sequences.append(seq_data)
labels.append(seq_label)return np.array(sequences), np.array(labels)
= create_sequences(train_data[features].values, time_steps=24)
X_train, y_train
# Reshape data for LSTM
= X_train.reshape((X_train.shape[0], X_train.shape[1], X_train.shape[2]))
X_train
# 2. Build the LSTM Model
= Sequential()
model 50, return_sequences=False, input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(LSTM(0.2))
model.add(Dropout(1))
model.add(Dense(
# Compile the model
compile(optimizer='adam', loss='mean_squared_error')
model.
# Train the model
=20, batch_size=32)
model.fit(X_train, y_train, epochs
# 3. Predict Demand for April to June 2024
# Assuming we start with the test data from Jan to March 2024
# Prepare the test set (January to March 2024)
'Hour'] = pd.to_datetime(test_data['Start Time'], format='%I:%M %p').dt.hour
test_data['Hour_sin'] = np.sin(2 * np.pi * test_data['Hour'] / 24)
test_data['Hour_cos'] = np.cos(2 * np.pi * test_data['Hour'] / 24)
test_data['Day_of_week_num'] = test_data['Day of the Week'].map(day_of_week_mapping)
test_data['Day_of_week_sin'] = np.sin(2 * np.pi * test_data['Day_of_week_num'] / 7)
test_data['Day_of_week_cos'] = np.cos(2 * np.pi * test_data['Day_of_week_num'] / 7)
test_data[
= create_sequences(test_data[features].values, time_steps=24)
X_test, y_test
# Reshape test data
= X_test.reshape((X_test.shape[0], X_test.shape[1], X_test.shape[2]))
X_test
# Predict for Jan-Mar 2024
= model.predict(X_test)
predictions
# Scale predictions back to original scale
= scaler.inverse_transform(np.concatenate([np.zeros((predictions.shape[0], 4)), predictions], axis=1))[:, -1]
predicted_demand
# Compare predictions for April 2024
= test_data['Hourly Demand Met (in MW)'].values[-predictions.shape[0]:]
actual_demand
# Calculate MAPE for January to March 2024
= mean_absolute_percentage_error(actual_demand, predicted_demand) * 100
mape print(f'MAPE for Jan-Mar 2024: {mape:.2f}%')
# 4. Visualize Results
=(10,6))
plt.figure(figsize='Actual Demand')
plt.plot(actual_demand, label='Predicted Demand', alpha=0.7)
plt.plot(predicted_demand, label'LSTM Demand Forecasting for Northern Region (Jan-Mar 2024)')
plt.title('Time (Hourly)')
plt.xlabel('Demand (MW)')
plt.ylabel(
plt.legend() plt.show()
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import mean_absolute_percentage_error
# Load the dataset
= pd.read_excel('NR_Demand.xlsx')
data
# Convert 'Date' to datetime object
'Date'] = pd.to_datetime(data['Date'])
data[
# Filter the data for 2023 and 2024
= data[data['Date'].dt.year == 2023]
train_data = data[(data['Date'].dt.year == 2024) & (data['Date'].dt.month <= 3)]
test_data
# Apply Moving Average on training data (e.g., 7-day or 24-hour window)
= 24 # Use 24-hour moving average for hourly data
window_size 'MA_Demand'] = train_data['Hourly Demand Met (in MW)'].rolling(window=window_size).mean()
train_data[
# Drop NaN values created by the rolling window
=True)
train_data.dropna(inplace
# Predict using the last available moving average from the training set for 2024 data
= train_data['MA_Demand'].iloc[-1]
last_moving_average 'MA_Prediction'] = last_moving_average # Using constant prediction
test_data[
# Calculate MAPE for January-March 2024
= test_data['Hourly Demand Met (in MW)'].values
actual_demand = test_data['MA_Prediction'].values
predicted_demand
= mean_absolute_percentage_error(actual_demand, predicted_demand) * 100
mape print(f'MAPE: {mape:.2f}%')
# Plot results
=(10,6))
plt.figure(figsize'Date'], actual_demand, label='Actual Demand')
plt.plot(test_data['Date'], predicted_demand, label='Predicted Demand (Moving Average)', alpha=0.7)
plt.plot(test_data['Moving Average Demand Forecasting for Northern Region (Jan-Mar 2024)')
plt.title('Date')
plt.xlabel('Demand (MW)')
plt.ylabel(
plt.legend() plt.show()
C:\Users\A\AppData\Local\Temp\ipykernel_4352\2793989846.py:18: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
train_data['MA_Demand'] = train_data['Hourly Demand Met (in MW)'].rolling(window=window_size).mean()
C:\Users\A\AppData\Local\Temp\ipykernel_4352\2793989846.py:21: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
train_data.dropna(inplace=True)
C:\Users\A\AppData\Local\Temp\ipykernel_4352\2793989846.py:25: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
test_data['MA_Prediction'] = last_moving_average # Using constant prediction
MAPE: 15.04%
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pprint
%matplotlib inline
= pd.read_excel("NR_Demand.xlsx")
df print("="*50)
print("First Five Rows", "\n")
print(df.head(2), "\n")
print("="*50)
print("Information About Dataset", "\n")
print(df.info(), "\n")
print("="*50)
print("Describe the Dataset", "\n")
print(df.describe(), "\n")
print("="*50)
print("Null Values", "\n")
print(df.isnull().sum(), "\n")
==================================================
First Five Rows
Region Date Day of the Week Start Time End Time \
0 Northern Region 2023-01-01 Sunday 12:00 AM 1:00 AM
1 Northern Region 2023-01-01 Sunday 1:00 AM 2:00 AM
Hourly Demand Met (in MW)
0 38793.37
1 36485.33
==================================================
Information About Dataset
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 11664 entries, 0 to 11663
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Region 11664 non-null object
1 Date 11664 non-null datetime64[ns]
2 Day of the Week 11664 non-null object
3 Start Time 11664 non-null object
4 End Time 11664 non-null object
5 Hourly Demand Met (in MW) 11664 non-null float64
dtypes: datetime64[ns](1), float64(1), object(4)
memory usage: 546.9+ KB
None
==================================================
Describe the Dataset
Date Hourly Demand Met (in MW)
count 11664 11664.000000
mean 2023-08-31 12:00:00 51977.455921
min 2023-01-01 00:00:00 27465.880000
25% 2023-05-02 00:00:00 44210.032500
50% 2023-08-31 12:00:00 51330.625000
75% 2023-12-31 00:00:00 58970.912500
max 2024-04-30 00:00:00 80793.890000
std NaN 10418.895695
==================================================
Null Values
Region 0
Date 0
Day of the Week 0
Start Time 0
End Time 0
Hourly Demand Met (in MW) 0
dtype: int64
import pandas as pd
import matplotlib.pyplot as plt
# Load the dataset
= pd.read_excel('NR_Demand.xlsx')
data
# Convert 'Date' to datetime object
'Date'] = pd.to_datetime(data['Date'])
data[
# Select one day from each season (adjust dates as needed for your dataset)
= data[(data['Date'] == '2023-01-15')] # Winter (January)
winter_day = data[(data['Date'] == '2023-04-15')] # Spring (April)
spring_day = data[(data['Date'] == '2023-07-15')] # Summer (July)
summer_day = data[(data['Date'] == '2023-10-15')] # Autumn (October)
autumn_day
# Plot hourly demand for each season day
=(10,6))
plt.figure(figsize'Start Time'], winter_day['Hourly Demand Met (in MW)'], label='Winter - 15 Jan', marker='o')
plt.plot(winter_day['Start Time'], spring_day['Hourly Demand Met (in MW)'], label='Spring - 15 April', marker='o')
plt.plot(spring_day['Start Time'], summer_day['Hourly Demand Met (in MW)'], label='Summer - 15 July', marker='o')
plt.plot(summer_day['Start Time'], autumn_day['Hourly Demand Met (in MW)'], label='Autumn - 15 Oct', marker='o')
plt.plot(autumn_day[
# Customize plot
'Hourly Demand for Four Days Representing Each Season (2023) for NR Region')
plt.title('Time of Day')
plt.xlabel('Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout()
# Show plot
plt.show()
# Extract all Data Like Year MOnth Day Time etc
= df
dataset "Month"] = pd.to_datetime(df["Date"]).dt.month
dataset["Year"] = pd.to_datetime(df["Date"]).dt.year
dataset["Date"] = pd.to_datetime(df["Date"]).dt.date
dataset["Time"] = pd.to_datetime(df["Start Time"]).dt.time
dataset["Day"] = pd.to_datetime(df["Date"]).dt.day_name()
dataset[= df.set_index("Date")
dataset = pd.to_datetime(dataset.index)
dataset.index 5) dataset.head(
C:\Users\A\AppData\Local\Temp\ipykernel_4352\1607697221.py:6: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format.
dataset["Time"] = pd.to_datetime(df["Start Time"]).dt.time
Region | Day of the Week | Start Time | End Time | Hourly Demand Met (in MW) | Month | Year | Time | Day | |
---|---|---|---|---|---|---|---|---|---|
Date | |||||||||
1970-01-01 | Northern Region | Sunday | 12:00 AM | 1:00 AM | 38793.37 | 1 | 1970 | 00:00:00 | Thursday |
1970-01-01 | Northern Region | Sunday | 1:00 AM | 2:00 AM | 36485.33 | 1 | 1970 | 01:00:00 | Thursday |
1970-01-01 | Northern Region | Sunday | 2:00 AM | 3:00 AM | 35203.58 | 1 | 1970 | 02:00:00 | Thursday |
1970-01-01 | Northern Region | Sunday | 3:00 AM | 4:00 AM | 35020.51 | 1 | 1970 | 03:00:00 | Thursday |
1970-01-01 | Northern Region | Sunday | 4:00 AM | 5:00 AM | 36340.32 | 1 | 1970 | 04:00:00 | Thursday |
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.holtwinters import ExponentialSmoothing
# Load the dataset
= pd.read_excel('NR_Demand.xlsx')
data
# Convert 'Date' to datetime object
'Date'] = pd.to_datetime(data['Date'])
data[
# Aggregate data by day for 2023 and Jan-Mar 2024
'Daily Demand'] = data.groupby('Date')['Hourly Demand Met (in MW)'].transform('sum')
data[= data[['Date', 'Daily Demand']].drop_duplicates()
daily_data
# Separate train and test data
= daily_data[daily_data['Date'].dt.year == 2023]
train_data = daily_data[(daily_data['Date'].dt.year == 2024) & (daily_data['Date'].dt.month <= 3)]
test_data
# Plot daily demand for Jan-Mar 2024
=(10,6))
plt.figure(figsize'Date'], test_data['Daily Demand'], label='Actual Daily Demand', marker='o')
plt.plot(test_data['Daily Demand for Jan-Mar 2024')
plt.title('Date')
plt.xlabel('Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout()
plt.show()
# Apply Exponential Smoothing (Holt-Winters) to predict the next 3 months (April-June 2024)
= ExponentialSmoothing(train_data['Daily Demand'], seasonal='add', seasonal_periods=90).fit()
model = model.forecast(90) # Forecasting for April, May, and June (90 days)
forecast
# Plot actual vs predicted values
=(10,6))
plt.figure(figsize'Date'], train_data['Daily Demand'], label='Train Data (2023)')
plt.plot(train_data['Date'], test_data['Daily Demand'], label='Test Data (Jan-Mar 2024)')
plt.plot(test_data[='2024-04-01', periods=90, freq='D'), forecast, label='Forecast (Apr-Jun 2024)', linestyle='--', marker='o')
plt.plot(pd.date_range(start
'Daily Demand Forecast for April-June 2024 using Exponential Smoothing')
plt.title('Date')
plt.xlabel('Daily Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
df.head()
Region | Date | Day of the Week | Start Time | End Time | Hourly Demand Met (in MW) | Month | Year | Time | Day | |
---|---|---|---|---|---|---|---|---|---|---|
0 | Northern Region | 1970-01-01 | Sunday | 12:00 AM | 1:00 AM | 38793.37 | 1 | 1970 | 00:00:00 | Thursday |
1 | Northern Region | 1970-01-01 | Sunday | 1:00 AM | 2:00 AM | 36485.33 | 1 | 1970 | 01:00:00 | Thursday |
2 | Northern Region | 1970-01-01 | Sunday | 2:00 AM | 3:00 AM | 35203.58 | 1 | 1970 | 02:00:00 | Thursday |
3 | Northern Region | 1970-01-01 | Sunday | 3:00 AM | 4:00 AM | 35020.51 | 1 | 1970 | 03:00:00 | Thursday |
4 | Northern Region | 1970-01-01 | Sunday | 4:00 AM | 5:00 AM | 36340.32 | 1 | 1970 | 04:00:00 | Thursday |
from matplotlib import style
= plt.figure()
fig = plt.subplot2grid((1,1), (0,0))
ax1
'ggplot')
style.use(
# Add label argument for the line plot to enable legend
=dataset["Start Time"], y=dataset["Hourly Demand Met (in MW)"], data=df, label='Hourly Demand',errorbar=('ci', 95), estimator=np.mean)
sns.lineplot(x
set(rc={'figure.figsize':(15,6)})
sns.
"NR - Mean Hourly Energy Consumption in Year 2023")
plt.title("Hours")
plt.xlabel("Energy in MW")
plt.ylabel(True)
plt.grid(
# Now the legend will work since label is provided
plt.legend()
# Rotate the x-axis labels for better readability
for label in ax1.xaxis.get_ticklabels():
90)
label.set_rotation(
plt.show()
from matplotlib import style
= plt.figure()
fig = plt.subplot2grid((1,1), (0,0))
ax1
'ggplot')
style.use(
# Add label argument for the line plot to enable legend
=dataset["Start Time"], y=dataset["Hourly Demand Met (in MW)"], data=df, label='Hourly Demand',errorbar=('ci', 95), estimator=np.median)
sns.lineplot(x
set(rc={'figure.figsize':(15,6)})
sns.
"NR - Median Hourly Energy Consumption in Year 2023")
plt.title("Hours")
plt.xlabel("Energy in MW")
plt.ylabel(True)
plt.grid(
# Now the legend will work since label is provided
plt.legend()
# Rotate the x-axis labels for better readability
for label in ax1.xaxis.get_ticklabels():
90)
label.set_rotation(
plt.show()
# Extract actual April 2024 data
= daily_data[(daily_data['Date'].dt.year == 2024) & (daily_data['Date'].dt.month == 4)]
actual_april_data
# Extract predicted April 2024 data (from forecast)
= forecast[:30] # First 30 days of forecast corresponds to April
predicted_april_data
# Plot comparison
=(10,6))
plt.figure(figsize'Date'], actual_april_data['Daily Demand'], label='Actual April 2024 Demand', marker='o')
plt.plot(actual_april_data[='2024-04-01', periods=30, freq='D'), predicted_april_data, label='Predicted April 2024 Demand', linestyle='--', marker='o')
plt.plot(pd.date_range(start
'Comparison of Actual vs Predicted Daily Demand for April 2024')
plt.title('Date')
plt.xlabel('Daily Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# Assuming the data is already loaded, and actual demand for April 2024 is present
= data[(data['Date'].dt.year == 2024) & (data['Date'].dt.month == 4)]['Hourly Demand Met (in MW)'].values
actual_april_2024
# Use MAPE from 2023 data to predict April 2024 (assume `mape` is already calculated)
= data[(data['Date'].dt.year == 2023) & (data['Date'].dt.month == 4)]['Hourly Demand Met (in MW)'].values
train_april_2023 = train_april_2023 * (1 + mape / 100)
predicted_april_2024
# Create a date range for April 2024
= pd.date_range(start='2024-04-01', periods=len(actual_april_2024), freq='H')
dates_april_2024
# Plot actual vs predicted
=(12, 6))
plt.figure(figsize
# Plot actual April 2024 data
='Actual April 2024', color='blue')
plt.plot(dates_april_2024, actual_april_2024, label
# Plot predicted April 2024 data
='Predicted April 2024 (MAPE)', linestyle='--', color='green')
plt.plot(dates_april_2024, predicted_april_2024, label
# Add labels and title
'Actual vs Predicted Demand for April 2024 (Using MAPE)')
plt.title('Date')
plt.xlabel('Hourly Demand Met (in MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
# Aggregate hourly data to daily demand
= daily_data[(daily_data['Date'].dt.year == 2023) & (daily_data['Date'].dt.month == 4)].groupby(daily_data['Date'].dt.strftime('%d-%m'))['Daily Demand'].sum()
daily_demand_2023 = daily_data[(daily_data['Date'].dt.year == 2024) & (daily_data['Date'].dt.month == 4)]
actual_april_data
# Calculate MAPE between 2023 data and predicted values
= np.mean(np.abs((daily_demand_2023 - daily_demand_2023.mean()) / daily_demand_2023)) * 100
mape
# Use MAPE to predict April 2024 based on April 2023 data
= daily_demand_2023 * (1 + (mape / 100))
predicted_april_data
# Plot comparison
=(10,6))
plt.figure(figsize
# Actual April 2024
'Date'], actual_april_data['Daily Demand'], label='Actual April 2024 Demand', marker='o')
plt.plot(actual_april_data[
# Predicted April 2024 using MAPE
='2024-04-01', periods=len(predicted_april_data), freq='D'),
plt.plot(pd.date_range(start='Predicted April 2024 Demand (MAPE)', linestyle='--', marker='o')
predicted_april_data.values, label
# Add titles and labels
'Comparison of Actual vs Predicted Daily Demand for April 2024 (MAPE)')
plt.title('Date')
plt.xlabel('Daily Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
from sklearn.metrics import mean_absolute_percentage_error
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# Load the dataset
= pd.read_excel('NR_Demand.xlsx')
data
# Convert 'Date' to datetime object
'Date'] = pd.to_datetime(data['Date'])
data[
# Aggregate daily demand
'Daily Demand'] = data.groupby('Date')['Hourly Demand Met (in MW)'].transform('sum')
data[= data[['Date', 'Daily Demand']].drop_duplicates()
daily_data
# Separate 2023 data for Jan-Mar
= daily_data[(daily_data['Date'].dt.year == 2023) & (daily_data['Date'].dt.month <= 3)]
train_2023
# Separate 2024 Jan-Mar data and remove Feb 29 to handle the leap year
= daily_data[(daily_data['Date'].dt.year == 2024) & (daily_data['Date'].dt.month <= 3) & (daily_data['Date'] != '2024-02-29')]
test_2024
# Calculate MAPE between Jan-Mar 2023 and Jan-Mar 2024
= mean_absolute_percentage_error(train_2023['Daily Demand'].values, test_2024['Daily Demand'].values) * 100
mape print(f'MAPE between Jan-Mar 2023 and Jan-Mar 2024: {mape:.2f}%')
# Extrapolate for April-June 2024 based on MAPE
# Get the data from 2023 for Apr-Jun and adjust by the calculated deviation (MAPE)
= daily_data[(daily_data['Date'].dt.year == 2023) & (daily_data['Date'].dt.month >= 4) & (daily_data['Date'].dt.month <= 6)]
train_apr_jun_2023 = train_apr_jun_2023['Daily Demand'].values * (1 + (mape / 100))
predicted_apr_jun_2024
# Plot actual 2023 and predicted 2024 data for Apr-Jun
=(10,6))
plt.figure(figsize'Date'], train_apr_jun_2023['Daily Demand'], label='Actual Apr-Jun 2023', marker='o')
plt.plot(train_apr_jun_2023[='2024-04-01', periods=len(predicted_apr_jun_2024), freq='D'), predicted_apr_jun_2024, label='Predicted Apr-Jun 2024', linestyle='--', marker='o')
plt.plot(pd.date_range(start
'Predicted Apr-Jun 2024 Demand Based on Deviation from Jan-Mar 2024 vs 2023')
plt.title('Date')
plt.xlabel('Daily Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
MAPE between Jan-Mar 2023 and Jan-Mar 2024: 8.70%
# Combine actual Jan-Mar 2024 and predicted/extrapolated Jan-Apr 2024 data
# Extract the actual data for Jan-Mar 2024 and April 2024
= test_2024['Daily Demand'].values
actual_jan_mar_2024 = daily_data[(daily_data['Date'].dt.year == 2024) & (daily_data['Date'].dt.month == 4)]['Daily Demand'].values
actual_april_2024
# Extrapolate Jan-Apr 2024 based on deviation (MAPE)
= daily_data[(daily_data['Date'].dt.year == 2023) & (daily_data['Date'].dt.month <= 4)]
train_jan_apr_2023 = train_jan_apr_2023['Daily Demand'].values * (1 + (mape / 100))
predicted_jan_apr_2024
# Combine dates for extrapolated Jan-Apr 2024
= pd.date_range(start='2024-01-01', periods=len(predicted_jan_apr_2024), freq='D')
dates_jan_apr_2024
# Combine actual Jan-Apr 2024 data with the rest of the predicted data for May-Dec
= np.concatenate([actual_april_2024, predicted_jul_dec_2024])
predicted_may_dec_2024
# Plot actual vs predicted for Jan-Apr 2024
=(10,6))
plt.figure(figsize
# Plot actual Jan-Apr 2024 data (all in one color)
='2024-01-01', periods=len(actual_jan_mar_2024)+len(actual_april_2024), freq='D'),
plt.plot(pd.date_range(start='Actual Jan-Apr 2024', linestyle='-', color='blue')
np.concatenate([actual_jan_mar_2024, actual_april_2024]), label
# Plot extrapolated Jan-Apr 2024 data
='Predicted Jan-Apr 2024', linestyle='--', color='green')
plt.plot(dates_jan_apr_2024, predicted_jan_apr_2024,label#label='Extrapolated Jan-Apr 2024'
# Plot predicted May-Dec 2024 data
='2024-05-01', periods=len(predicted_may_dec_2024), freq='D'), predicted_may_dec_2024, label='Predicted May-Dec 2024', linestyle='--', color='red')
plt.plot(pd.date_range(start
# Plot the actual 2023 data for reference
'Date'], train_data['Daily Demand'], label='Train Data (2023)', linestyle='-', color='orange')
plt.plot(train_data[
'Actual and Predicted Jan-Apr 2024 vs Predicted May-Dec 2024 Demand')
plt.title('Date')
plt.xlabel('Daily Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) File D:\Softwares\Anaconda\Lib\site-packages\pandas\core\indexes\base.py:3805, in Index.get_loc(self, key) 3804 try: -> 3805 return self._engine.get_loc(casted_key) 3806 except KeyError as err: File index.pyx:167, in pandas._libs.index.IndexEngine.get_loc() File index.pyx:196, in pandas._libs.index.IndexEngine.get_loc() File pandas\\_libs\\hashtable_class_helper.pxi:7081, in pandas._libs.hashtable.PyObjectHashTable.get_item() File pandas\\_libs\\hashtable_class_helper.pxi:7089, in pandas._libs.hashtable.PyObjectHashTable.get_item() KeyError: 'Daily Demand' The above exception was the direct cause of the following exception: KeyError Traceback (most recent call last) Cell In[377], line 32 29 plt.plot(pd.date_range(start='2024-05-01', periods=len(predicted_may_dec_2024), freq='D'), predicted_may_dec_2024, label='Predicted May-Dec 2024', linestyle='--', color='red') 31 # Plot the actual 2023 data for reference ---> 32 plt.plot(train_data['Date'], train_data['Daily Demand'], label='Train Data (2023)', linestyle='-', color='orange') 34 plt.title('Actual and Predicted Jan-Apr 2024 vs Predicted May-Dec 2024 Demand') 35 plt.xlabel('Date') File D:\Softwares\Anaconda\Lib\site-packages\pandas\core\frame.py:4102, in DataFrame.__getitem__(self, key) 4100 if self.columns.nlevels > 1: 4101 return self._getitem_multilevel(key) -> 4102 indexer = self.columns.get_loc(key) 4103 if is_integer(indexer): 4104 indexer = [indexer] File D:\Softwares\Anaconda\Lib\site-packages\pandas\core\indexes\base.py:3812, in Index.get_loc(self, key) 3807 if isinstance(casted_key, slice) or ( 3808 isinstance(casted_key, abc.Iterable) 3809 and any(isinstance(x, slice) for x in casted_key) 3810 ): 3811 raise InvalidIndexError(key) -> 3812 raise KeyError(key) from err 3813 except TypeError: 3814 # If we have a listlike key, _check_indexing_error will raise 3815 # InvalidIndexError. Otherwise we fall through and re-raise 3816 # the TypeError. 3817 self._check_indexing_error(key) KeyError: 'Daily Demand'
# Combine actual Jan-Mar 2024 and predicted/extrapolated Jan-Apr 2024 data
# Extract the actual data for Jan-Mar 2024 and April 2024
= test_2024['Daily Demand'].values
actual_jan_mar_2024 = daily_data[(daily_data['Date'].dt.year == 2024) & (daily_data['Date'].dt.month == 4)]['Daily Demand'].values
actual_april_2024
# Extrapolate Jan-Apr 2024 based on deviation (MAPE)
= daily_data[(daily_data['Date'].dt.year == 2023) & (daily_data['Date'].dt.month <= 4)]
train_jan_apr_2023 = train_jan_apr_2023['Daily Demand'].values * (1 + (mape / 100))
predicted_jan_apr_2024
# Combine dates for extrapolated Jan-Apr 2024
= pd.date_range(start='2024-01-01', periods=len(predicted_jan_apr_2024), freq='D')
dates_jan_apr_2024
# Combine actual Jan-Apr 2024 data with the rest of the predicted data for May-Dec
= np.concatenate([actual_april_2024, predicted_jul_dec_2024])
predicted_may_dec_2024
# Plot actual vs predicted for Jan-Apr 2024
=(10,6))
plt.figure(figsize
# Plot actual Jan-Apr 2024 data (all in one color)
='2024-01-01', periods=len(actual_jan_mar_2024)+len(actual_april_2024), freq='D'),
plt.plot(pd.date_range(start='Actual Jan-Apr 2024', linestyle='-', color='blue')
np.concatenate([actual_jan_mar_2024, actual_april_2024]), label
# Plot extrapolated Jan-Apr 2024 data
='Predicted Jan-Apr 2024', linestyle='--', color='green')
plt.plot(dates_jan_apr_2024, predicted_jan_apr_2024,label#label='Extrapolated Jan-Apr 2024'
# Plot predicted May-Dec 2024 data
='2024-05-01', periods=len(predicted_may_dec_2024), freq='D'), predicted_may_dec_2024, label='Predicted May-Dec 2024', linestyle='--', color='red')
plt.plot(pd.date_range(start
# Plot the actual 2023 data for reference
'Date'], train_data['Daily Demand'], label='Train Data (2023)', linestyle='-', color='orange')
plt.plot(train_data[
'Actual and Predicted Jan-Apr 2024 vs Predicted May-Dec 2024 Demand')
plt.title('Date')
plt.xlabel('Daily Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
# Combine actual Jan-Mar 2024 and predicted/extrapolated Jan-Apr 2024 data
# Extract the actual data for Jan-Mar 2024 and April 2024
= test_2024['Daily Demand'].values
actual_jan_mar_2024 = daily_data[(daily_data['Date'].dt.year == 2024) & (daily_data['Date'].dt.month == 4)]['Daily Demand'].values
actual_april_2024
# Extrapolate Jan-Apr 2024 based on deviation (MAPE)
= daily_data[(daily_data['Date'].dt.year == 2023) & (daily_data['Date'].dt.month <= 4)]
train_jan_apr_2023 = train_jan_apr_2023['Daily Demand'].values * (1 + (mape / 100))
predicted_jan_apr_2024
# Combine dates for extrapolated Jan-Apr 2024
= pd.date_range(start='2024-01-01', periods=len(predicted_jan_apr_2024), freq='D')
dates_jan_apr_2024
# Combine actual Jan-Apr 2024 data with the rest of the predicted data for May-June
= np.concatenate([actual_april_2024, predicted_jul_dec_2024[:61]]) # Predicting up to June
predicted_may_jun_2024
# Plot actual vs predicted for Jan-Jun 2024
=(10,6))
plt.figure(figsize
# Plot actual Jan-Apr 2024 data (all in one color)
='2024-01-01', periods=len(actual_jan_mar_2024)+len(actual_april_2024), freq='D'),
plt.plot(pd.date_range(start='Actual Jan-Apr 2024', linestyle='-', color='blue')
np.concatenate([actual_jan_mar_2024, actual_april_2024]), label
# Plot extrapolated Jan-Apr 2024 data
='Predicted Jan-Apr 2024', linestyle='--', color='green')
plt.plot(dates_jan_apr_2024, predicted_jan_apr_2024, label
# Plot predicted May-Jun 2024 data
='2024-05-01', periods=len(predicted_may_jun_2024), freq='D'), predicted_may_jun_2024, label='Predicted May-Jun 2024', linestyle='--', color='red')
plt.plot(pd.date_range(start
# Plot the actual 2023 data for reference (not zoomed in)
# You can remove this if it clutters the zoomed view
'Date'], train_data['Daily Demand'], label='Train Data (2023)', linestyle='-', color='orange')
plt.plot(train_data[
# Set the x-limits to zoom into Jan-Jun 2024
'2024-01-01'), pd.Timestamp('2024-06-30'))
plt.xlim(pd.Timestamp(
'Zoomed: Actual and Extrapolated Jan-Apr 2024 vs Predicted May-Jun 2024 Demand')
plt.title('Date')
plt.xlabel('Daily Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
# Combine actual Jan-Mar 2024 and predicted/extrapolated data for Jan-Jun 2024
# Extract the actual data for Jan-Mar 2024 and April 2024
= test_2024['Daily Demand'].values
actual_jan_mar_2024 = daily_data[(daily_data['Date'].dt.year == 2024) & (daily_data['Date'].dt.month == 4)]['Daily Demand'].values
actual_april_2024
# Extrapolate Jan-Apr 2024 based on deviation (MAPE)
= daily_data[(daily_data['Date'].dt.year == 2023) & (daily_data['Date'].dt.month <= 4)]
train_jan_apr_2023 = train_jan_apr_2023['Daily Demand'].values * (1 + (mape / 100))
predicted_jan_jun_2024
# Combine dates for extrapolated Jan-Jun 2024
= pd.date_range(start='2024-01-01', periods=len(predicted_jan_jun_2024), freq='D')
dates_jan_jun_2024
# Combine actual Jan-Mar 2024 with predicted data from April to June for a continuous prediction
= np.concatenate([actual_jan_mar_2024, predicted_jan_jun_2024[len(actual_jan_mar_2024):]])
predicted_data_2024
# Plot the combined actual and predicted data for Jan-Jun 2024
=(10,6))
plt.figure(figsize
# Plot actual Jan-Mar 2024 data
='2024-01-01', periods=len(actual_jan_mar_2024), freq='D'),
plt.plot(pd.date_range(start='Actual Jan-Mar 2024', linestyle='-', color='blue')
actual_jan_mar_2024, label
# Plot predicted Jan-Jun 2024 data
='2024-04-01', periods=len(predicted_data_2024), freq='D'), predicted_data_2024, label='Predicted Jan-Jun 2024', linestyle='--', color='green')
plt.plot(pd.date_range(start
# Set the x-limits to zoom into Jan-Jun 2024
'2024-01-01'), pd.Timestamp('2024-06-30'))
plt.xlim(pd.Timestamp(
'Zoomed: Actual Jan-Mar 2024 vs Predicted Jan-Jun 2024 Demand')
plt.title('Date')
plt.xlabel('Daily Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
5) data.head(
Region | Date | Day of the Week | Start Time | End Time | Hourly Demand Met (in MW) | Daily Demand | |
---|---|---|---|---|---|---|---|
0 | Northern Region | 2023-01-01 | Sunday | 12:00 AM | 1:00 AM | 38793.37 | 1123719.4 |
1 | Northern Region | 2023-01-01 | Sunday | 1:00 AM | 2:00 AM | 36485.33 | 1123719.4 |
2 | Northern Region | 2023-01-01 | Sunday | 2:00 AM | 3:00 AM | 35203.58 | 1123719.4 |
3 | Northern Region | 2023-01-01 | Sunday | 3:00 AM | 4:00 AM | 35020.51 | 1123719.4 |
4 | Northern Region | 2023-01-01 | Sunday | 4:00 AM | 5:00 AM | 36340.32 | 1123719.4 |
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# Convert 'Start Time' and 'End Time' to proper datetime objects for sorting
'Start Time'] = pd.to_datetime(df['Start Time'], format='%I:%M %p')
df[
# Extract actual hourly data for Jan-Mar 2024
= data['Hourly Demand Met (in MW)'].values
actual_jan_mar_2024_hourly
# Extrapolate Jan-Apr 2024 based on hourly deviation (MAPE)
= daily_data[(daily_data['Date'].dt.year == 2023) & (daily_data['Date'].dt.month <= 4)]
train_jan_apr_2023_hourly = data['Hourly Demand Met (in MW)'].values * (1 + (mape / 100))
predicted_jan_jun_2024_hourly
# Combine dates for extrapolated hourly data from Jan-Jun 2024
= pd.date_range(start='2024-01-01 00:00:00', periods=len(predicted_jan_jun_2024_hourly), freq='h')
dates_jan_jun_2024_hourly
# Combine actual Jan-Mar 2024 with predicted hourly data from April to June
= np.concatenate([actual_jan_mar_2024_hourly, predicted_jan_jun_2024_hourly[len(actual_jan_mar_2024_hourly):]])
predicted_data_2024_hourly
# Plot the combined actual and predicted hourly data for Jan-Jun 2024
=(12,6))
plt.figure(figsize
# Plot actual Jan-Mar 2024 hourly data
len(actual_jan_mar_2024_hourly)],
plt.plot(dates_jan_jun_2024_hourly[:='Actual Jan-Mar 2024 (Hourly)', linestyle='-', color='blue')
actual_jan_mar_2024_hourly, label
# Plot predicted Jan-Jun 2024 hourly data
='Predicted Jan-Jun 2024 (Hourly)', linestyle='--', color='green')
plt.plot(dates_jan_jun_2024_hourly, predicted_data_2024_hourly, label
# Set title and labels
'Hourly Energy Consumption: Actual vs Predicted (Jan-Jun 2024)')
plt.title('Date')
plt.xlabel('Hourly Energy Demand (MW)')
plt.ylabel(=45)
plt.xticks(rotation
plt.legend()
plt.tight_layout() plt.show()
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import LSTM, Dense
import matplotlib.pyplot as plt
# Extract relevant columns for LSTM
= data['Hourly Demand Met (in MW)'].values.reshape(-1, 1)
hourly_demand
# Scale the data between 0 and 1 using MinMaxScaler
= MinMaxScaler(feature_range=(0, 1))
scaler = scaler.fit_transform(hourly_demand)
scaled_data
# Set the time step (how many hours to use for prediction)
= 24 # Using 24 hours (1 day) as a time step for prediction
time_step
# Prepare the training data
= [], []
X_train, y_train for i in range(time_step, len(scaled_data)):
- time_step:i, 0])
X_train.append(scaled_data[i 0])
y_train.append(scaled_data[i,
= np.array(X_train), np.array(y_train)
X_train, y_train
# Reshape X_train to be in the format (samples, time_steps, features)
= np.reshape(X_train, (X_train.shape[0], X_train.shape[1], 1))
X_train
# Build the LSTM Model
= Sequential()
model =50, return_sequences=True, input_shape=(X_train.shape[1], 1)))
model.add(LSTM(units=50))
model.add(LSTM(units1))
model.add(Dense(
# Compile the model
compile(optimizer='adam', loss='mean_squared_error')
model.
# Train the model
=20, batch_size=32)
model.fit(X_train, y_train, epochs
# Predict future values
= model.predict(X_train)
predictions
# Inverse transform the predictions back to the original scale
= scaler.inverse_transform(predictions)
predictions
# Visualize the actual vs predicted values
=(12,6))
plt.figure(figsize='Actual')
plt.plot(hourly_demand[time_step:], label='Predicted')
plt.plot(predictions, label'Actual vs Predicted Hourly Demand (LSTM)')
plt.title('Time')
plt.xlabel('Hourly Demand Met (in MW)')
plt.ylabel(
plt.legend() plt.show()
D:\Softwares\Anaconda\Lib\site-packages\keras\src\layers\rnn\rnn.py:204: UserWarning: Do not pass an `input_shape`/`input_dim` argument to a layer. When using Sequential models, prefer using an `Input(shape)` object as the first layer in the model instead.
super().__init__(**kwargs)
Epoch 1/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 13s 19ms/step - loss: 0.0241
Epoch 2/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 6s 16ms/step - loss: 0.0040
Epoch 3/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 11s 19ms/step - loss: 0.0015
Epoch 4/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 6s 17ms/step - loss: 0.0010
Epoch 5/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 8s 21ms/step - loss: 9.3667e-04
Epoch 6/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 8s 21ms/step - loss: 7.6057e-04
Epoch 7/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 10s 19ms/step - loss: 7.3900e-04
Epoch 8/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - loss: 7.0528e-04
Epoch 9/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - loss: 6.7631e-04
Epoch 10/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 6s 17ms/step - loss: 6.6344e-04
Epoch 11/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 7s 18ms/step - loss: 6.9789e-04
Epoch 12/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 10s 18ms/step - loss: 6.6491e-04
Epoch 13/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 7s 19ms/step - loss: 6.3890e-04
Epoch 14/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 10s 18ms/step - loss: 6.2410e-04
Epoch 15/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 6s 17ms/step - loss: 6.2724e-04
Epoch 16/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 7s 19ms/step - loss: 6.2907e-04
Epoch 17/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 7s 19ms/step - loss: 6.1487e-04
Epoch 18/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 6s 18ms/step - loss: 6.3083e-04
Epoch 19/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 10s 17ms/step - loss: 5.6240e-04
Epoch 20/20
364/364 ━━━━━━━━━━━━━━━━━━━━ 6s 16ms/step - loss: 5.6765e-04
364/364 ━━━━━━━━━━━━━━━━━━━━ 5s 8ms/step
import matplotlib.dates as mdates
# Create a date range for the x-axis based on your data
= pd.date_range(start="2023-01-01", periods=len(hourly_demand), freq='H')
date_range
# Plot the results
=(12, 6))
plt.figure(figsize
# Training data
len(train_data)], train_data, label='Training Data')
plt.plot(date_range[:
# Test data
len(train_data):len(hourly_demand)], test_data, label='Forecasted Data', color='orange')
plt.plot(date_range[
# Format x-axis to show dates
'%Y-%m-%d'))
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter(
plt.gca().xaxis.set_major_locator(mdates.MonthLocator())
# Rotate x-axis labels for readability
plt.gcf().autofmt_xdate()
# Add title and labels
'SARIMA Forecast for Hourly Demand')
plt.title('Date')
plt.xlabel('Hourly Demand Met (in MW)')
plt.ylabel(
plt.legend()
plt.tight_layout() plt.show()
C:\Users\A\AppData\Local\Temp\ipykernel_4352\2660867132.py:4: FutureWarning: 'H' is deprecated and will be removed in a future version, please use 'h' instead.
date_range = pd.date_range(start="2023-01-01", periods=len(hourly_demand), freq='H')
import matplotlib.dates as mdates
# Create a date range for the x-axis based on your data
= pd.date_range(start="2023-01-01", periods=len(hourly_demand), freq='H')
date_range
# Plot the results
=(12, 6))
plt.figure(figsize
# Training data
len(train_data)], train_data, label='Training Data')
plt.plot(date_range[:
# Test data
len(train_data):len(hourly_demand)], test_data, label='Forecasted Data', color='orange')
plt.plot(date_range[
# Format x-axis to show dates
'%Y-%m-%d'))
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter(
plt.gca().xaxis.set_major_locator(mdates.MonthLocator())
# Rotate x-axis labels for readability
plt.gcf().autofmt_xdate()
# Add title and labels
'SARIMA Forecast for Hourly Demand')
plt.title('Date')
plt.xlabel('Hourly Demand Met (in MW)')
plt.ylabel(
plt.legend()
plt.tight_layout() plt.show()
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[389], line 13 10 plt.plot(date_range[:len(train_data)], train_data, label='Training Data') 12 # Test data ---> 13 plt.plot(date_range[len(train_data):len(hourly_demand)], test_data, label='Forecasted Data', color='orange') 15 # Format x-axis to show dates 16 plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) File D:\Softwares\Anaconda\Lib\site-packages\matplotlib\pyplot.py:3590, in plot(scalex, scaley, data, *args, **kwargs) 3582 @_copy_docstring_and_deprecators(Axes.plot) 3583 def plot( 3584 *args: float | ArrayLike | str, (...) 3588 **kwargs, 3589 ) -> list[Line2D]: -> 3590 return gca().plot( 3591 *args, 3592 scalex=scalex, 3593 scaley=scaley, 3594 **({"data": data} if data is not None else {}), 3595 **kwargs, 3596 ) File D:\Softwares\Anaconda\Lib\site-packages\matplotlib\axes\_axes.py:1724, in Axes.plot(self, scalex, scaley, data, *args, **kwargs) 1481 """ 1482 Plot y versus x as lines and/or markers. 1483 (...) 1721 (``'green'``) or hex strings (``'#008000'``). 1722 """ 1723 kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D) -> 1724 lines = [*self._get_lines(self, *args, data=data, **kwargs)] 1725 for line in lines: 1726 self.add_line(line) File D:\Softwares\Anaconda\Lib\site-packages\matplotlib\axes\_base.py:303, in _process_plot_var_args.__call__(self, axes, data, *args, **kwargs) 301 this += args[0], 302 args = args[1:] --> 303 yield from self._plot_args( 304 axes, this, kwargs, ambiguous_fmt_datakey=ambiguous_fmt_datakey) File D:\Softwares\Anaconda\Lib\site-packages\matplotlib\axes\_base.py:499, in _process_plot_var_args._plot_args(self, axes, tup, kwargs, return_kwargs, ambiguous_fmt_datakey) 496 axes.yaxis.update_units(y) 498 if x.shape[0] != y.shape[0]: --> 499 raise ValueError(f"x and y must have same first dimension, but " 500 f"have shapes {x.shape} and {y.shape}") 501 if x.ndim > 2 or y.ndim > 2: 502 raise ValueError(f"x and y can be no greater than 2D, but have " 503 f"shapes {x.shape} and {y.shape}") ValueError: x and y must have same first dimension, but have shapes (11299,) and (91, 2)
# Plot the results
=(12, 6))
plt.figure(figsize
# Training data
len(train_data)], train_data, label='Training Data')
plt.plot(date_range[:
# Forecasted data (previously labeled as 'Test Data')
len(train_data):len(hourly_demand)], test_data, label='Forecasted Data', color='orange')
plt.plot(date_range[
# Format x-axis to show dates
'%Y-%m-%d'))
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter(
plt.gca().xaxis.set_major_locator(mdates.MonthLocator())
# Rotate x-axis labels for readability
plt.gcf().autofmt_xdate()
# Zoom into Jan 2024 to June 2024
'2024-01-01'), pd.Timestamp('2024-04-30'))
plt.xlim(pd.Timestamp(
# Add title and labels
'SARIMA Forecast for Hourly Demand (Jan 2024 - June 2024)')
plt.title('Date')
plt.xlabel('Hourly Demand Met (in MW)')
plt.ylabel(
plt.legend()
plt.tight_layout() plt.show()