File size: 4,392 Bytes
d6165ca
fde69ff
 
6d819a2
d6165ca
f27b577
24d2e79
fde69ff
 
 
 
 
 
 
8c7c72e
fde69ff
 
 
f33264f
 
 
 
 
 
 
 
d6165ca
fde69ff
 
 
 
 
 
 
 
d6165ca
f33264f
d6165ca
fde69ff
d6165ca
fde69ff
d6165ca
fde69ff
 
 
d6165ca
0b7e8df
 
5f049bf
d6165ca
 
4f991e0
d6165ca
4f991e0
 
d6165ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f049bf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
import streamlit as st
import pandas as pd
from io import BytesIO
from itertools import product
from statsmodels.tsa.holtwinters import ExponentialSmoothing
import plotly.express as px
st.set_page_config(layout="wide")
# Function to run the Exponential Smoothing Model
def run_exp_smoothing(city_data, trend, damped_trend, seasonal, seasonal_period):
    try:
        model = ExponentialSmoothing(city_data, trend=trend, damped_trend=damped_trend, seasonal=seasonal, seasonal_periods=seasonal_period)
        model_fit = model.fit(optimized=True)
        return model_fit.forecast(steps=6), model_fit.aic
    except Exception as e:
        st.error(f"An error occurred during model fitting: {e}")
        return None, None

def create_data():
    data = pd.read_csv('accident_count.csv', parse_dates=True, index_col=0)
    data.index = pd.to_datetime(data.index, format='%Y%m')
    data = data.groupby('City').resample('M').sum().reset_index()
    data.index = data['Accident Month Bracket']
    data = data.drop(['Accident Month Bracket'],axis=1)
    data.index = data.index.strftime('%Y-%m')
    return data

# Function to convert DataFrame to Excel
def to_excel(df):
    output = BytesIO()
    writer = pd.ExcelWriter(output, engine='xlsxwriter')
    df.to_excel(writer, sheet_name='Sheet1')
    writer.save()
    processed_data = output.getvalue()
    return processed_data

# Initialize session state for best parameters
if 'best_params' not in st.session_state:
    st.session_state.best_params = {'trend': None, 'damped_trend': False, 'seasonal': None, 'seasonal_period': 12}

st.title("Exponential Smoothing Forecasting")

# Data preparation
data = create_data()
unique_cities = data['City'].unique()

# Creating tabs for each city
tabs = st.tabs([city for city in unique_cities])

for tab, city in zip(tabs, unique_cities):
    with tab:
        # Sliders for parameter adjustment, using session state values as defaults
        trend = st.select_slider('Select Trend', options=['add', 'mul', None], value=st.session_state.best_params['trend'],key=city+'1')
        damped_trend = False
        seasonal = st.select_slider('Select Seasonal', options=['add', 'mul', None], value=st.session_state.best_params['seasonal'],key=city+'2')
        seasonal_period = st.slider('Seasonal Period', 1, 24, value=st.session_state.best_params['seasonal_period'],key=city+'3')

        city_data = data[data['City'] == city]['Accident Count']
        forecast, aic = run_exp_smoothing(city_data, trend, damped_trend, seasonal, seasonal_period)

        if forecast is not None:
            st.write(f"Best Parameters with AIC: {aic}")
            st.write(f"Trend: {trend}, Damped Trend: {damped_trend}, Seasonal: {seasonal}, Seasonal Period: {seasonal_period}")
            forecast_index = pd.date_range(start=city_data.index[-1], periods=7, freq='M')[1:]
            forecast_index = forecast_index.to_period('M')  # Convert to period index with monthly frequency
            forecast_df = pd.DataFrame(forecast, columns=['Forecast'])
            forecast_df = forecast_df.round(0)
            st.table(forecast_df)
            fig = px.line(forecast_df, x=forecast_df.index, y="Forecast")
            st.plotly_chart(fig)

        # Grid search button
        if st.button(f'Run Grid Search for {city}'):
            best_aic = float('inf')
            best_params = None
            for param_set in product(['add', 'mul', None], [False], ['add', 'mul', None], [12]):
                _, temp_aic = run_exp_smoothing(city_data, *param_set)
                if temp_aic and temp_aic < best_aic:
                    best_aic = temp_aic
                    best_params = param_set

            # Updating session state with the best parameters
            st.session_state.best_params = {
                'trend': best_params[0],
                'damped_trend': best_params[1],
                'seasonal': best_params[2],
                'seasonal_period': best_params[3]
            }
            st.write(f"Best Parameters for {city}: {best_params} with AIC: {best_aic}")

        
        # Export to Excel button
        if st.button(f'Export {city} to Excel'):
            df_to_export = forecast_df
            excel_data = to_excel(df_to_export)
            st.download_button(label='📥 Download Excel', data=excel_data, file_name=f'{city}_forecast.xlsx', mime='application/vnd.ms-excel')