import streamlit as st import pandas as pd import numpy as np import datetime from datetime import timedelta import pandas as pd import numpy as np # from datetime import datetime import matplotlib.pyplot as plt from statsmodels.tsa.seasonal import seasonal_decompose from statsmodels import api as sm from statsmodels.graphics import tsaplots from statsmodels.tsa.statespace.sarimax import SARIMAX pd.options.display.float_format = '{:.2f}'.format st.write('Калькулятор для Дениса') # import streamlit as st st.sidebar.title('Выбор параметров для расчета влияния фичи') with st.sidebar: count_view = st.number_input( "Введите охват аудитории - сколько пользователей увидят Вашу фичу/виджет/баннер", min_value=0, # Минимальное значение step=1, # Шаг единицы format='%d', # Формат для целых чисел # max_value=(df1['ЗП в вакансии'].max() - 50000) # ("IT", "Продажи"), value = 1 ) ctr = st.number_input( "Конверсия в клик", value = 0.01 ) ctr_connect = st.number_input( "Конверсия в подключение услуги", value = 0.01 ) money = st.selectbox( "Хотите ли Вы указать значение среднего чека или при расчете брать прогнозируемое значений", options=["Выставлю сам", "Использовать прогноз"], key=f"1", index=None, ) if money == 'Выставлю сам': money_self = st.number_input( "Введите значение среднего чека", value = 1 ) duration = st.selectbox( "Введите количество месяцев, на протяжении которых желаете оценивать влияние фичи", options=[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24], key=f"2", count_month = st.number_input( "Введите количество месяцев прогноза", min_value=0, # Минимальное значение step=1, # Шаг единицы format='%d', # Формат для целых чисел # max_value=(df1['ЗП в вакансии'].max() - 50000) # ("IT", "Продажи") value=12 ) # min_value=0, # Минимальное значение # step=1, # Шаг единицы # format='%d', # Формат для целых чисел # # max_value=(df1['ЗП в вакансии'].max() - 50000) # # ("IT", "Продажи") ) date_start = st.date_input("Выберите дату старта акции:", datetime.date(2024, 10, 1)) st.write("Вы выбрали дату:", date_start) # Заголовок приложения st.title("Расчет прогнозных значений моделью SARIMA, с добавлением параментов фичи") st.write("Файл должен содержать 3 колонки: Дата, Оборот, Средний чек") st.write("Если Вы не подгружаете свои данные - расчет производится по дефолтным данным") # Используем file_uploader для загрузки файла uploaded_file = st.file_uploader("Выберите файл Excel", type=["xlsx"]) # Проверяем, был ли загружен файл if uploaded_file is not None: # Читаем файл Excel в DataFrame df = pd.read_excel(uploaded_file) # Отображаем загруженные данные st.write("Загруженные данные:") st.dataframe(df) @st.cache_data def load_file(path): data = pd.read_excel(path) return data @st.cache_data def fit_model(data_list): seasonal_order = (1, 1, 1, 12) # Настройте параметры сезонности (P, D, Q, s) model = SARIMAX(data_list.dropna(), seasonal_order=seasonal_order) model_fit = model.fit() forecast = model_fit.forecast(steps=count_month) return forecast data = load_file('Файл для построения прогноза.xlsx') data = data.rename(columns={'Оборот по всем копилкам за месяц': 'Оборот', 'Изменение ср чека': 'Средний чек'}) st.dataframe(data, width=1100, height=250) data['Дата'] = pd.to_datetime(data['Дата'], format="%d.%m.%Y") # изменяем тип данных на дату data.set_index('Дата', inplace=True) data = data.rename(columns={'Оборот по всем копилкам за месяц': 'Оборот', 'Изменение ср чека': 'Средний чек'}) # if count_month: # seasonal_order = (1, 1, 1, 12) # Настройте параметры сезонности (P, D, Q, s) # model = SARIMAX(data['Оборот'].dropna(), seasonal_order=seasonal_order) # model_fit = model.fit() # forecast_new = model_fit.forecast(steps=count_month) forecast_new = fit_model(data['Оборот']) fig, ax = plt.subplots(figsize=(10, 5)) # plt.figure(figsize=(10, 5)) # plt.plot(train['Оборот по всем копилкам за месяц'], label='Train') ax.plot(data['Оборот'], label='Исторические данные', color='orange') ax.plot(forecast_new.index, forecast_new, label='Прогноз', color='green', linestyle='--') ax.set_title('Прогнозирование общего оборота АН с помощью SARIMA') ax.legend() ax.grid() # ax.show() st.pyplot(fig) # данные по среднему чеку также спрогнозируем помесячно # Обучаем модель SARIMA # seasonal_order = (1, 1, 1, 12) # Настройте параметры сезонности (P, D, Q, s) # model = SARIMAX(data['Средний чек'].dropna(), seasonal_order=seasonal_order) # model_fit = model.fit() # # Прогнозируем # forecast_chek = model_fit.forecast(steps=count_month) forecast_chek = fit_model(data['Средний чек']) # Визуализируем результаты fig, ax = plt.subplots(figsize=(10, 5)) # plt.plot(train['Оборот по всем копилкам за месяц'], label='Train') ax.plot(data['Средний чек'], label='Исторические данные', color='orange') ax.plot(forecast_chek.index, forecast_chek, label='Прогноз', color='green', linestyle='--') ax.set_title('Прогнозирование с помощью SARIMA среднего чека') ax.legend() ax.grid() st.pyplot(fig) st.subheader('Прогнозные значения без влияния фичи') df_no_feature = pd.DataFrame() df_no_feature['Дата'] = forecast_new.index df_no_feature['Оборот'] = list(forecast_new) df_no_feature['Средний чек'] = list(forecast_chek) st.dataframe(df_no_feature) 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] st.subheader('Визуализация влияния фичи') month_start = date_start summ_from_feature = 0 new_summ_with_features = [] if money == 'Выставлю сам': forecast_chek = [money_self for i in range(len(forecast_new))] list_retention = list_retention[:duration+1] + [0 for i in range(25)] for i in range(len(forecast_new)): # print(f"Сумма прогноза без добавления фичи в период {forecast_new.index[i].date()} -", forecast_new[i]) if (forecast_new.index[i].date() >= month_start) & ( forecast_new.index[i].date() <= month_start + timedelta(days=180)): summ_from_feature += count_view * ctr * ctr_connect * forecast_chek[i] * list_retention[i] # print("Доп сумма от фичи:", summ_from_feature) new_summ_with_features.append(summ_from_feature + forecast_new[i]) i += 1 else: new_summ_with_features.append(forecast_new[i]) # Визуализируем результаты fig, ax = plt.subplots(figsize=(10, 5)) # plt.plot(train['Оборот по всем копилкам за месяц'], label='Train') ax.plot(data['Оборот'], label='Исторические данные', color='orange') ax.plot(forecast_new.index, forecast_new, label='Прогноз', color='green', linestyle='--') ax.plot(forecast_new.index, new_summ_with_features, label='Прогноз с добавлением фичи', color='red', linestyle='--') ax.set_title('Прогнозирование с помощью SARIMA') ax.legend() ax.grid() st.pyplot(fig) st.subheader('Данные с учетом влияния фичи') df_no_feature['Прогноз с учетом фичи'] = list(new_summ_with_features) st.dataframe(df_no_feature)