Dacho688 commited on
Commit
a2d5210
·
0 Parent(s):

Initial commit

Browse files
.gitattributes ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
.gitignore ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ .env
2
+ .vscode/
3
+ .venv/
4
+ .__pycache__/
Dockerfile ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Dockerfile
2
+ FROM python:3.12-slim
3
+ WORKDIR /app
4
+ COPY requirements.txt .
5
+ RUN pip install --no-cache-dir -r requirements.txt
6
+ COPY ./app .
7
+ CMD ["bokeh", "serve", "--port", "7860", "--allow-websocket-origin=*", "app.py"]
README.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Auto Forecast Tool
3
+ emoji: 📈
4
+ colorFrom: blue
5
+ colorTo: gray
6
+ sdk: docker
7
+ app_port: 7860
8
+ pinned: false
9
+ ---
10
+ The above yaml frontmatter is required to configure huggingface space.
11
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
__pycache__/app.cpython-312.pyc ADDED
Binary file (806 Bytes). View file
 
app/__pycache__/forecast.cpython-312.pyc ADDED
Binary file (815 Bytes). View file
 
app/app.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from bokeh.io import curdoc
2
+ from bokeh.models import FileInput, Div, ColumnDataSource, DataTable, TableColumn, TextInput, NumericInput,Button
3
+ from bokeh.layouts import column,row
4
+ from bokeh.plotting import figure
5
+ import base64
6
+ import io
7
+ import pandas as pd
8
+ import forecast
9
+
10
+ #Initialize an empty data source, table, and figure
11
+ source = ColumnDataSource(data={})
12
+ columns = [] # Initially empty, will be built on upload
13
+ data_table = DataTable(source=source, columns=columns, width=300, height=400)
14
+ table_title = Div(text="""<h2>Data Table</h2>""", width=300)
15
+ fig = figure(title = "Auto Forecast Plot",width=1500,height=800)
16
+ fig.title.text_font_style = 'bold'
17
+ fig.title.text_color = 'black'
18
+ fig.title.text_font_size = '14pt'
19
+ fig.title.align = 'center'
20
+ #Create bokeh objects
21
+ title = Div(text="""
22
+ <div style="text-align: center; width: 100%;">
23
+ <h1>Auto Forecast Tool</h1>
24
+ </div>
25
+ """, width=1800,align='center',sizing_mode='stretch_width')
26
+ status_msg = Div(text = "<b>STATUS:</b> Ready")
27
+ file_input = FileInput(accept=".csv",title="Upload Time Series Data as CSV")
28
+ seasonality = NumericInput(value=1,title="Number of periods in season? Enter 1 if no seasonality.", mode='int')
29
+ n_ahead = NumericInput(value=12,title="Number of periods to forecast?", mode='int')
30
+ column_name = TextInput(title="Column name to forecast?")
31
+ forecast = Button(label="Auto Forecast")
32
+
33
+
34
+ def update_status():
35
+ #Update status
36
+ status_msg.text = "<b>STATUS:</b> Running......"
37
+ curdoc().add_next_tick_callback(upload_callback)
38
+
39
+ def upload_callback():
40
+ # Decode upload, save to memory, and read in as df
41
+ decoded = base64.b64decode(file_input.value)
42
+ file = io.BytesIO(decoded)
43
+ df = pd.read_csv(file)
44
+
45
+ # Make forecasts and append to df
46
+ forecasts = forecast.forecast(df,column_name.value,seasonality.value,n_ahead.value)
47
+ new_data = pd.DataFrame()
48
+ new_data['Forecasts'] = forecasts
49
+ df = pd.concat([df, new_data], ignore_index=True).reset_index()
50
+
51
+ #Update the data source
52
+ source.data = df.to_dict('list')
53
+ #Update the columns based on the new file's headers
54
+ data_table.columns = [TableColumn(field=col, title=col) for col in df.columns]
55
+
56
+ #Update figure with all data
57
+ fig.line(x='index',y= 'Sales',source=source,line_width=2)
58
+ fig.line(x='index',y= 'Forecasts',source=source,line_width=2,line_color='Red')
59
+ #Update status
60
+ status_msg.text = "<b>STATUS:</b> Complete!"
61
+
62
+ forecast.on_click(update_status)
63
+
64
+ layout = column(row(title, align='center'),row(column(status_msg,file_input, seasonality, n_ahead, column_name,forecast, table_title, data_table),fig),sizing_mode='stretch_both')
65
+ curdoc().add_root(layout)
app/forecast.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from pmdarima import auto_arima
2
+ import pandas as pd
3
+
4
+ def forecast(df, column_name: str, seasonality: int, ahead: int):
5
+ data = df[column_name]
6
+ oos = round(len(data) * .1)
7
+ model = auto_arima(data,m = seasonality, max_order = 10, information_criterion = 'oob', stepwise = False, out_of_sample_size = oos, scoring = 'mse')
8
+ forecasts = model.predict(ahead,return_conf_int = False)
9
+ return forecasts
docker-compose.yaml ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ services:
2
+ app:
3
+ build: .
4
+ container_name: AutoForecast
5
+ restart: unless-stopped
6
+ ports:
7
+ - "7860:7860"
requirements.txt ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ bokeh==3.9.0
2
+ contourpy==1.3.3
3
+ Cython==3.2.4
4
+ Jinja2==3.1.6
5
+ joblib==1.5.3
6
+ MarkupSafe==3.0.3
7
+ narwhals==2.18.1
8
+ numpy==2.4.4
9
+ packaging==26.0
10
+ pandas==3.0.2
11
+ patsy==1.0.2
12
+ pillow==12.2.0
13
+ pmdarima==2.1.1
14
+ python-dateutil==2.9.0.post0
15
+ PyYAML==6.0.3
16
+ scikit-learn==1.8.0
17
+ scipy==1.17.1
18
+ setuptools==82.0.1
19
+ six==1.17.0
20
+ statsmodels==0.14.6
21
+ threadpoolctl==3.6.0
22
+ tornado==6.5.5
23
+ tzdata==2026.1
24
+ urllib3==2.6.3
25
+ xyzservices==2026.3.0
sample_ts.csv ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Sales
2
+ 25.43
3
+ 25.40261631
4
+ 25.25921236
5
+ 25.37212214
6
+ 25.59537742
7
+ 25.71449737
8
+ 25.83492987
9
+ 26.06598132
10
+ 26.24807293
11
+ 26.29073998
12
+ 26.47911422
13
+ 26.64143188
14
+ 26.54648005
15
+ 26.20449163
16
+ 26.15804831
17
+ 26.34006063
18
+ 26.65306602
19
+ 26.67016132
20
+ 26.86504956
21
+ 26.45487684
22
+ 26.28864757
23
+ 26.24155545
24
+ 25.98584189
25
+ 26.19768115
26
+ 25.99336282
27
+ 25.7098198
28
+ 25.40067164
29
+ 25.49413624
30
+ 25.86170657
31
+ 25.57582803
32
+ 25.45306549
33
+ 25.19219256
34
+ 25.69617506
35
+ 25.74281787
36
+ 25.76476699
37
+ 26.10184043
38
+ 26.17668546
39
+ 25.96149588
40
+ 25.96916466
41
+ 26.34714157
42
+ 26.71505289
43
+ 27.21283004
44
+ 27.59688634
45
+ 27.18419775
46
+ 27.42551023
47
+ 27.9160403
48
+ 28.14207525
49
+ 28.25457145
50
+ 28.4948408
51
+ 28.53134638
52
+ 27.99483363
53
+ 28.19582371
54
+ 28.03514658
55
+ 27.94852817
56
+ 27.70558018
57
+ 28.21989493
58
+ 28.22234232
59
+ 28.11163131
60
+ 28.39043792
61
+ 28.76427468
62
+ 28.77743576
63
+ 28.81627813
64
+ 28.90543479
65
+ 28.96039756
66
+ 29.27505977
67
+ 29.53442255
68
+ 29.47826423
69
+ 30.24456748
70
+ 30.28091309
71
+ 29.35889895
72
+ 29.61603448
73
+ 29.62164427
74
+ 29.20166099
75
+ 28.98293796
76
+ 29.52118563
77
+ 28.8210753
78
+ 28.86790893
79
+ 29.52749068
80
+ 29.27976979
81
+ 29.14817396
82
+ 28.815914
83
+ 28.54500723
84
+ 28.07540091
85
+ 28.05535895
86
+ 27.82826507
87
+ 28.07305168
88
+ 28.28592037
89
+ 28.31924593
90
+ 28.16129611
91
+ 27.98713574
92
+ 28.46008467
93
+ 27.97933622
94
+ 28.10981219
95
+ 28.14902559
96
+ 28.2020732
97
+ 28.36939803
98
+ 28.1405316
99
+ 28.43986795
100
+ 28.24326799
101
+ 27.83816661
102
+ 28.07991496
103
+ 28.26620122
104
+ 28.6233578
105
+ 28.64521264
106
+ 28.28176018
107
+ 28.65605903
108
+ 28.46357256
109
+ 28.62236099
110
+ 28.97059124
111
+ 28.43462732
112
+ 28.29492653
113
+ 28.49375449
114
+ 28.6629355
115
+ 28.25693418
116
+ 28.19665076
117
+ 28.09894706
118
+ 28.29157087
119
+ 28.16400833
120
+ 28.49138934
121
+ 28.82024867
sample_ts.xlsx ADDED
Binary file (11.7 kB). View file