File size: 4,359 Bytes
d6165ca
fde69ff
 
6d819a2
d6165ca
f27b577
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

# 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')