Spaces:
Sleeping
Sleeping
import streamlit as st | |
from scipy.stats import ttest_ind, norm | |
import pandas as pd | |
import numpy as np | |
from sklearn.model_selection import train_test_split | |
# Загрузка и предварительная обработка данных | |
df = pd.read_csv("task_data.csv", encoding='ISO-8859-1') | |
base_date = pd.Timestamp('2022-01-01') | |
df['Date'] = base_date + pd.to_timedelta(df['Date'] - 44562, unit='D') | |
# Отбор данных за март | |
df_march = df[df['Date'].dt.month == 3] | |
# Расчет медианных продаж для каждого магазина в марте | |
march_sales_median = df_march.groupby('STORE')['Qty'].median().reset_index(name='Median Sales March') | |
# Определение общей медианы продаж в марте | |
overall_median_sales_march = march_sales_median['Median Sales March'].median() | |
# Выборка магазинов с продажами вокруг общей медианы (10% от медианы) | |
close_to_median_stores = march_sales_median[ | |
abs(march_sales_median['Median Sales March'] - overall_median_sales_march) <= overall_median_sales_march * 0.1 | |
]['STORE'] | |
# Разделение выбранных магазинов на контрольную и тестовую группы | |
test_stores, control_stores = train_test_split(close_to_median_stores, test_size=0.5, random_state=42) | |
test_stores_codes = test_stores.tolist() | |
control_stores_codes = control_stores.tolist() | |
# Подготовка данных о количестве продаж для новых контрольной и тестовой групп | |
control_sales = df[df['STORE'].isin(control_stores_codes)]['Qty'] | |
test_sales = df[df['STORE'].isin(test_stores_codes)]['Qty'] | |
# Проведение t-теста | |
t_test_result = ttest_ind(control_sales, test_sales) | |
# Подготовка данных о качестве представленности для контрольной и тестовой групп за март | |
control_quality_march = df_march[df_march['STORE'].isin(control_stores_codes)]['Quality of presence'] | |
test_quality_march = df_march[df_march['STORE'].isin(test_stores_codes)]['Quality of presence'] | |
# Проведение t-теста для качества представленности за март | |
t_test_quality_result_march = ttest_ind(control_quality_march, test_quality_march) | |
control_sales_march = df_march[df_march['STORE'].isin(control_stores_codes)]['Qty'] | |
test_sales_march = df_march[df_march['STORE'].isin(test_stores_codes)]['Qty'] | |
# Расчет стандартных отклонений и размеров выборок | |
std_dev_control = control_sales_march.std(ddof=1) | |
std_dev_test = test_sales_march.std(ddof=1) | |
n_control = len(control_sales_march) | |
n_test = len(test_sales_march) | |
# Объединенное стандартное отклонение | |
std_dev_pooled = np.sqrt((std_dev_control**2 + std_dev_test**2) / 2) | |
# Уровень значимости и мощность | |
alpha = 0.05 | |
power = 0.8 | |
z_alpha = norm.ppf(1 - alpha / 2) | |
z_beta = norm.ppf(power) | |
# Расчет MDE | |
mde = (z_alpha + z_beta) * std_dev_pooled * np.sqrt(1/n_control + 1/n_test) | |
mde_percent = (mde / df_march['Qty'].mean()) * 100 # Процент от среднего количества продаж | |
median_quality = df_march['Quality of presence'].median() | |
# Разделение магазинов на группы с хорошей и плохой представленностью | |
good_quality_stores = df_march[df_march['Quality of presence'] > median_quality] | |
poor_quality_stores = df_march[df_march['Quality of presence'] <= median_quality] | |
# Расчет средней представленности для каждой группы | |
average_good_quality = good_quality_stores['Quality of presence'].mean() | |
average_poor_quality = poor_quality_stores['Quality of presence'].mean() | |
st.markdown(f""" | |
### Гипотезы для А/Б-теста | |
Так как магазины с высоким качеством представленности и магазины с низким качеством представленности имеют статистически значимое различие в средних количествах проданных батончиков, можно предположить, что увеличив среднюю представленность в магазинах с плохой представленностью, можно статистически значимо увеличить объем продаж в этих магазинах. | |
Гипотеза здесь заключается в том, что магазины с плохой представленностью демонстируют плохие продажи именно из-за качества представленности, а не из-за социально-демографических особенностей аудитории покупателей или территориальных особенностей расположения магазина. | |
Возможна и обратная ситуация: возможно, плохие продажи вызваны не плохой представленностью, а плохая представленность вызвана плохими продажами. | |
Н0 — если в магазинах с плохой представленностью увеличить среднюю представленность до среднего уровня магазинов с хорошей представленностью, то количество проданных баточников не изменится. | |
Н1 — если в магазинах с плохой представленностью увеличить среднюю представленность до среднего уровня магазинов с хорошей представленностью (средний уровень представленности в магазинах с хорошей представленностью: {average_good_quality:.2f}), то количество проданных баточников станет больше. | |
#### Расчеты | |
Так как на данный момент идёт февраль, я буду рассчитывать тест на март, с предположением, что данные показывают похожую сезонность в течение последних нескольких лет, и март 2024 года можно предсказывать, ориентируясь на март 2022 года. | |
На основе средней представленности батончиков в магазинах за март, магазины были разделены на группы с хорошей и плохой представленностью. | |
Магазины с хорошей представленностью — те, в которых средний уровень представленности в марте выше медианного. Cредний уровень прдставленности в магазинах с хорошей представленностью в марте: {average_good_quality:.2f}. | |
Магазины с плохой представленностью — те, в которых средний уровень представленности в марте ниже медианного. Cредний уровень прдставленности в магазинах с плохой представленностью в марте: {average_poor_quality:.2f}. | |
Для отбора магазинов для контрольной и тестовой группы, были отобраны магазины с продажами вокруг общей медианы (в пределах 10% от медианы). Таким образом, в тестовой и контрольной группе получилось по 46 и 47 магазинов соответственно. | |
Тестовая группа: {test_stores_codes} | |
Контрольная группа: {control_stores_codes} | |
Результаты t-теста по объему продаж: | |
- t-test: {t_test_result.statistic:.3f} | |
- P-value: {t_test_result.pvalue:.3f} | |
Результаты t-теста по качеству представленности: | |
- t-test: {t_test_quality_result_march.statistic:.3f} | |
- P-value: {t_test_quality_result_march.pvalue:.3f} | |
Результаты говорят о том, что магазины разделены на группы хорошо, и между двумя группами нет статистически значимых различий ни в уровне продаж, ни в уровне средней представленности в магазинах. | |
Я предлагаю проводить А/Б тест в течение марта, при такой продолжительности теста минимальным детектируемым эффектом от проведения теста будет {mde_percent:.3f}%. | |
Это означает, что для того, чтобы обнаружить статистически значимые изменения в продажах между контрольной и тестовой группами с уровнем значимости 0.05 и мощностью теста 0.8, изменение в количестве проданных батончиков должно быть не менее {mde_percent:.3f}% от среднего уровня продаж. | |
При этом продажи по результатам года в группе с низкой представленностью были более чем в 2 раза ниже, чем в группе с хорошей представленностью, что позволяет предполагать, что эффект от изменений, при условии того, что верна гипотеза Н1, будет значительно превышать минимальный детектируемый эффект. | |
""") | |