Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -1,7 +1,19 @@
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
st.write('Калькулятор для Дениса')
|
7 |
|
@@ -15,15 +27,18 @@ with st.sidebar:
|
|
15 |
step=1, # Шаг единицы
|
16 |
format='%d', # Формат для целых чисел
|
17 |
# max_value=(df1['ЗП в вакансии'].max() - 50000)
|
18 |
-
# ("IT", "Продажи")
|
|
|
19 |
)
|
20 |
|
21 |
ctr = st.number_input(
|
22 |
"Конверсия в клик",
|
|
|
23 |
)
|
24 |
|
25 |
ctr_connect = st.number_input(
|
26 |
"Конверсия в подключение услуги",
|
|
|
27 |
)
|
28 |
|
29 |
money = st.selectbox(
|
@@ -34,6 +49,7 @@ with st.sidebar:
|
|
34 |
if money == 'Выставлю сам':
|
35 |
money_self = st.number_input(
|
36 |
"Введите значение среднего чека",
|
|
|
37 |
)
|
38 |
|
39 |
duration = st.selectbox(
|
@@ -42,6 +58,7 @@ with st.sidebar:
|
|
42 |
|
43 |
|
44 |
|
|
|
45 |
# min_value=0, # Минимальное значение
|
46 |
# step=1, # Шаг единицы
|
47 |
# format='%d', # Формат для целых чисел
|
@@ -49,16 +66,26 @@ with st.sidebar:
|
|
49 |
# # ("IT", "Продажи")
|
50 |
)
|
51 |
|
52 |
-
date_start = st.date_input("Выберите дату старта акции:",
|
53 |
st.write("Вы выбрали дату:", date_start)
|
54 |
|
55 |
|
56 |
# Заголовок приложения
|
57 |
-
st.title("
|
58 |
-
|
|
|
59 |
# Используем file_uploader для загрузки файла
|
60 |
uploaded_file = st.file_uploader("Выберите файл Excel", type=["xlsx"])
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
# Проверяем, был ли загружен файл
|
63 |
if uploaded_file is not None:
|
64 |
# Читаем файл Excel в DataFrame
|
@@ -67,3 +94,95 @@ if uploaded_file is not None:
|
|
67 |
# Отображаем загруженные данные
|
68 |
st.write("Загруженные данные:")
|
69 |
st.dataframe(df)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
+
import datetime
|
5 |
+
from datetime import timedelta
|
6 |
+
import pandas as pd
|
7 |
+
import numpy as np
|
8 |
+
# from datetime import datetime
|
9 |
+
import matplotlib.pyplot as plt
|
10 |
+
from statsmodels.tsa.seasonal import seasonal_decompose
|
11 |
+
from statsmodels import api as sm
|
12 |
+
from statsmodels.graphics import tsaplots
|
13 |
+
from statsmodels.tsa.statespace.sarimax import SARIMAX
|
14 |
+
pd.options.display.float_format = '{:.2f}'.format
|
15 |
+
|
16 |
+
|
17 |
|
18 |
st.write('Калькулятор для Дениса')
|
19 |
|
|
|
27 |
step=1, # Шаг единицы
|
28 |
format='%d', # Формат для целых чисел
|
29 |
# max_value=(df1['ЗП в вакансии'].max() - 50000)
|
30 |
+
# ("IT", "Продажи"),
|
31 |
+
value = 1
|
32 |
)
|
33 |
|
34 |
ctr = st.number_input(
|
35 |
"Конверсия в клик",
|
36 |
+
value = 0.01
|
37 |
)
|
38 |
|
39 |
ctr_connect = st.number_input(
|
40 |
"Конверсия в подключение услуги",
|
41 |
+
value = 0.01
|
42 |
)
|
43 |
|
44 |
money = st.selectbox(
|
|
|
49 |
if money == 'Выставлю сам':
|
50 |
money_self = st.number_input(
|
51 |
"Введите значение среднего чека",
|
52 |
+
value = 1
|
53 |
)
|
54 |
|
55 |
duration = st.selectbox(
|
|
|
58 |
|
59 |
|
60 |
|
61 |
+
|
62 |
# min_value=0, # Минимальное значение
|
63 |
# step=1, # Шаг единицы
|
64 |
# format='%d', # Формат для целых чисел
|
|
|
66 |
# # ("IT", "Продажи")
|
67 |
)
|
68 |
|
69 |
+
date_start = st.date_input("Выберите дату старта акции:", datetime.date(2024, 10, 1))
|
70 |
st.write("Вы выбрали дату:", date_start)
|
71 |
|
72 |
|
73 |
# Заголовок приложения
|
74 |
+
st.title("Расчет прогнозных значений моделью SARIMA, с добавлением параментов фичи")
|
75 |
+
st.write("Файл должен содержать 3 колонки: Дата, Оборот, Средний чек")
|
76 |
+
st.write("Если Вы не подгружаете свои данные - расчет производится по дефолтным данным")
|
77 |
# Используем file_uploader для загрузки файла
|
78 |
uploaded_file = st.file_uploader("Выберите файл Excel", type=["xlsx"])
|
79 |
|
80 |
+
count_month = st.number_input(
|
81 |
+
"Введите количество месяцев прогноза",
|
82 |
+
min_value=0, # Минимальное значение
|
83 |
+
step=1, # Шаг единицы
|
84 |
+
format='%d', # Формат для целых чисел
|
85 |
+
# max_value=(df1['ЗП в вакансии'].max() - 50000)
|
86 |
+
# ("IT", "Продажи")
|
87 |
+
value=12
|
88 |
+
)
|
89 |
# Проверяем, был ли загружен файл
|
90 |
if uploaded_file is not None:
|
91 |
# Читаем файл Excel в DataFrame
|
|
|
94 |
# Отображаем загруженные данные
|
95 |
st.write("Загруженные данные:")
|
96 |
st.dataframe(df)
|
97 |
+
|
98 |
+
|
99 |
+
|
100 |
+
data = pd.read_excel('Файл для построения прогноза.xlsx')
|
101 |
+
st.dataframe(data, width=1100, height=250)
|
102 |
+
data['Дата'] = pd.to_datetime(data['Дата'], format="%d.%m.%Y") # изменяем тип данных на дату
|
103 |
+
data.set_index('Дата', inplace=True)
|
104 |
+
data = data.rename(columns={'Оборот по всем копилкам за месяц': 'Оборот', 'Изменение ср чека': 'Средний чек'})
|
105 |
+
|
106 |
+
# if count_month:
|
107 |
+
seasonal_order = (1, 1, 1, 12) # Настройте параметры сезонности (P, D, Q, s)
|
108 |
+
model = SARIMAX(data['Оборот'].dropna(), seasonal_order=seasonal_order)
|
109 |
+
model_fit = model.fit()
|
110 |
+
forecast_new = model_fit.forecast(steps=count_month)
|
111 |
+
|
112 |
+
fig, ax = plt.subplots(figsize=(10, 5))
|
113 |
+
# plt.figure(figsize=(10, 5))
|
114 |
+
# plt.plot(train['Оборот по всем копилкам за месяц'], label='Train')
|
115 |
+
ax.plot(data['Оборот'], label='Исторические данные', color='orange')
|
116 |
+
ax.plot(forecast_new.index, forecast_new, label='Прогноз', color='green', linestyle='--')
|
117 |
+
ax.set_title('Прогнозирование общего оборота АН с помощью SARIMA')
|
118 |
+
ax.legend()
|
119 |
+
ax.grid()
|
120 |
+
# ax.show()
|
121 |
+
st.pyplot(fig)
|
122 |
+
|
123 |
+
# данные по среднему чеку также спрогнозируем помесячно
|
124 |
+
# Обучаем модель SARIMA
|
125 |
+
seasonal_order = (1, 1, 1, 12) # Настройте параметры сезонности (P, D, Q, s)
|
126 |
+
model = SARIMAX(data['Средний чек'].dropna(), seasonal_order=seasonal_order)
|
127 |
+
model_fit = model.fit()
|
128 |
+
# Прогнозируем
|
129 |
+
forecast_chek = model_fit.forecast(steps=count_month)
|
130 |
+
# Визуализируем результаты
|
131 |
+
fig, ax = plt.subplots(figsize=(10, 5))
|
132 |
+
# plt.plot(train['Оборот по всем копилкам за месяц'], label='Train')
|
133 |
+
ax.plot(data['Средний чек'], label='Исторические данные', color='orange')
|
134 |
+
ax.plot(forecast_chek.index, forecast_chek, label='Прогноз', color='green', linestyle='--')
|
135 |
+
ax.set_title('Прогнозирование с помощью SARIMA среднего чека')
|
136 |
+
ax.legend()
|
137 |
+
ax.grid()
|
138 |
+
st.pyplot(fig)
|
139 |
+
|
140 |
+
st.subheader('Прогнозные значения без влияния фичи')
|
141 |
+
df_no_feature = pd.DataFrame()
|
142 |
+
df_no_feature['Дата'] = forecast_new.index
|
143 |
+
df_no_feature['Оборот'] = list(forecast_new)
|
144 |
+
df_no_feature['Средний чек'] = list(forecast_chek)
|
145 |
+
st.dataframe(df_no_feature)
|
146 |
+
|
147 |
+
list_retention = [0.48, 0.58, 0.52, 0.47, 0.44, 0.42, 0.4, 0.38, 0.37, 0.35, 0.34, 0.33, 0.32, 0.31, 0.30, 0.29, 0.28, 0.27, 0.26, 0.25, 0.24]
|
148 |
+
|
149 |
+
st.subheader('Визуализация влияния фичи')
|
150 |
+
|
151 |
+
month_start = date_start
|
152 |
+
|
153 |
+
summ_from_feature = 0
|
154 |
+
new_summ_with_features = []
|
155 |
+
|
156 |
+
if money == 'Выставлю сам':
|
157 |
+
forecast_chek = [money_self for i in range(len(forecast_new))]
|
158 |
+
|
159 |
+
list_retention = list_retention[:duration+1] + [0 for i in range(25)]
|
160 |
+
for i in range(len(forecast_new)):
|
161 |
+
|
162 |
+
# print(f"Сумма прогноза без добавления фичи в период {forecast_new.index[i].date()} -", forecast_new[i])
|
163 |
+
if (forecast_new.index[i].date() >= month_start) & (
|
164 |
+
forecast_new.index[i].date() <= month_start + timedelta(days=180)):
|
165 |
+
summ_from_feature += count_view * ctr * ctr_connect * forecast_chek[i] * list_retention[i]
|
166 |
+
# print("Доп сумма от фичи:", summ_from_feature)
|
167 |
+
|
168 |
+
new_summ_with_features.append(summ_from_feature + forecast_new[i])
|
169 |
+
i += 1
|
170 |
+
else:
|
171 |
+
new_summ_with_features.append(forecast_new[i])
|
172 |
+
|
173 |
+
|
174 |
+
# Визуализируем результаты
|
175 |
+
fig, ax = plt.subplots(figsize=(10, 5))
|
176 |
+
# plt.plot(train['Оборот по всем копилкам за месяц'], label='Train')
|
177 |
+
ax.plot(data['Оборот'], label='Исторические данные', color='orange')
|
178 |
+
ax.plot(forecast_new.index, forecast_new, label='Прогноз', color='green', linestyle='--')
|
179 |
+
ax.plot(forecast_new.index, new_summ_with_features, label='Прогноз с добавлением фичи', color='red', linestyle='--')
|
180 |
+
|
181 |
+
ax.set_title('Прогнозирование с помощью SARIMA')
|
182 |
+
ax.legend()
|
183 |
+
ax.grid()
|
184 |
+
st.pyplot(fig)
|
185 |
+
|
186 |
+
st.subheader('Данные с учетом влияния фичи')
|
187 |
+
df_no_feature['Прогноз с учетом фичи'] = list(new_summ_with_features)
|
188 |
+
st.dataframe(df_no_feature)
|