File size: 3,485 Bytes
a04211d
 
 
 
8dc3a0f
a04211d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8dc3a0f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8c05129
 
 
 
 
 
 
8dc3a0f
 
a04211d
8dc3a0f
 
 
 
 
a04211d
8dc3a0f
a04211d
8c05129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a04211d
 
8dc3a0f
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 gradio as gr
import pandas as pd
import pmdarima as pm
from pmdarima import auto_arima
import plotly.graph_objs as go

def forecast_time_series(file):
    # Load data
    data = pd.read_csv(file.name, skiprows=2)
    period_type = data.columns[0]
    data[period_type] = pd.to_datetime(data[period_type])
    data.set_index(period_type, inplace=True)

    # Fit the SARIMAX model automatically
    model = auto_arima(data)
    
    # Forecasting
    n_periods = 24  # Number of periods to forecast
    forecast, conf_int = model.predict(n_periods=n_periods, return_conf_int=True)
    
    # Create a DataFrame with the forecast and confidence intervals
    forecast_index = pd.date_range(start=data.index[-1], periods=n_periods + 1, freq=data.index.inferred_freq)[1:]
    forecast_df = pd.DataFrame(forecast, index=forecast_index, columns=['Forecast'])
    conf_int_df = pd.DataFrame(conf_int, index=forecast_index, columns=['Lower CI', 'Upper CI'])
    forecast_df = pd.concat([forecast_df, conf_int_df], axis=1)

    # Calculate the YoY change
    sum_last_12_original = data.iloc[-12:, 0].sum()
    sum_first_12_forecast = forecast_df['Forecast'].iloc[:12].sum()
    yoy_change = (sum_first_12_forecast - sum_last_12_original) / sum_last_12_original

    # Create an interactive plot with Plotly
    fig = go.Figure()
    fig.add_trace(go.Scatter(x=data.index, y=data.iloc[:, 0], mode='lines', name='Original Series'))
    fig.add_trace(go.Scatter(x=forecast_df.index, y=forecast_df['Forecast'], mode='lines', name='Forecast', line=dict(color='red')))
    fig.add_trace(go.Scatter(
        x=forecast_df.index,
        y=forecast_df['Lower CI'],
        fill=None,
        mode='lines',
        line=dict(color='pink'),
        showlegend=False
    ))
    fig.add_trace(go.Scatter(
        x=forecast_df.index,
        y=forecast_df['Upper CI'],
        fill='tonexty',
        mode='lines',
        line=dict(color='pink'),
        name='Confidence Interval'
    ))
    fig.update_layout(
        title='Original Time Series and Forecast with Confidence Intervals',
        xaxis_title='Date',
        yaxis_title='Values',
        legend=dict(
            orientation='h',
            yanchor='bottom',
            y=1.02,
            xanchor='right',
            x=1
        ),
        hovermode='x unified'
    )
    
    # Combine original data and forecast data into one DataFrame for export
    combined_df = pd.concat([data, forecast_df], axis=0)
    combined_file = 'combined_data.csv'
    combined_df.to_csv(combined_file)

    # Return plot file path and YoY change
    return fig, f'Year-over-Year Change in Sum of Values: {yoy_change:.2%}', combined_file

# Create Gradio interface using Blocks
with gr.Blocks(theme=gr.themes.Monochrome()) as interface:
    gr.Markdown("# Time Series Forecasting")
    gr.Markdown("Upload a CSV file with a time series to forecast the next 24 periods and see the YoY % change. Download the combined original and forecast data.")
    
    with gr.Row():
        file_input = gr.File(label="Upload Time Series CSV")
    
    with gr.Row():
        plot_output = gr.Plot(label="Time Series + Forecast Chart")
    
    with gr.Row():
        yoy_output = gr.Text(label="YoY % Change")
    
    with gr.Row():
        csv_output = gr.File(label="Download Combined Data CSV")
    
    file_input.change(forecast_time_series, inputs=file_input, outputs=[plot_output, yoy_output, csv_output])

# Launch the interface
interface.launch()