Автор: Евгений Бодягин, https://dsprog.pro
Введение
Необходимо проверить эффективность нового дизайна web-приложения. Есть прежний дизайн «A», есть новый дизайн «B». Проведем A-B тест. Оговоримся, что есть масса вариаций проведения A-B тестов. Необходимо учитывать нюансы анализируемого объекта/процесса в каждом отдельном случае. В данном материале будут показаны основные шаги A-B теста.
Дизайн эксперимента
- Нулевая гипотеза: Нет разницы в эффективности между дизайном A и B.
- Альтернативная гипотеза: Есть значительная разница в эффективности между дизайном A и B.
- Объект обработки: Две выборки сеансов посетителей сайта перемешанные случайным образом. Размер выборок одинаков.
- Целевая аудитория: Посетители сайта за последние 30 дней
- Метрики:
- Длительность проведения теста: 30 дней
- Уровни значимости:
- α = 0.05
- Кампании запускаются одновременно, а аудитория делится случайным образом.
Структура данных
Каждая строка данных представляет информацию о визитах пользователя на web-приложения.
- .
- Пользователь ID (User_ID): ID пользователя.
- Название кампании (Campaign_Name): Название кампании (дизайн А либо дизайн B).
- Просмотр контента (View): Сколько раз пользователь просмотрел контент на сайте.
- Клики (Click): Количество кликов на баннер. Количество пользователей которые пользовались дизайном А и дизайном B равны.
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline import sys import warnings warnings.filterwarnings('ignore') from scipy.stats import mannwhitneyu alpha = 0.05
Загрузка данных
alldata = pd.read_csv('input/Xab_group.csv') df_userAgg = pd.read_csv('input/Xab_group.csv') alldata.head()
User_ID | Campaign_Name | View | Click | |
---|---|---|---|---|
0 | 1 | a campaign | 4.0 | 0.0 |
1 | 2 | b campaign | 12.0 | 0.0 |
2 | 3 | a campaign | 1.0 | 0.0 |
3 | 4 | a campaign | 5.0 | 0.0 |
4 | 5 | a campaign | 8.0 | 0.0 |
Проверка на дубликаты и null значения
alldata.duplicated().sum()
0
alldata.isnull().sum()
User_ID 0
Campaign_Name 0
View 0
Click 0
dtype: int64
В исходных данных повторяющихся значений нет; null значений также нет.
grouped = alldata.groupby('Campaign_Name') a_group = grouped.get_group('a campaign') b_group = grouped.get_group('b campaign')
desired_palette = ["#0099cc", "#009900"] data_all = pd.concat([a_group, b_group]) fig, ax = plt.subplots(ncols=2, figsize=(18,6)) ax1 = sns.barplot(data=data_all, x='Campaign_Name', y='View', errorbar=('ci', False), ax=ax[0], estimator='sum', palette=desired_palette) ax2 = sns.barplot(data=data_all, x='Campaign_Name', y='Click', errorbar=('ci', False), ax=ax[1], estimator='sum', palette=desired_palette) # this content is from dsprog.pro ax1.set_title('View') ax2.set_title('Click') plt.show() a_group_View_sum = a_group['View'].sum() b_group_View_sum = b_group['View'].sum() a_group_Click_sum = a_group['Click'].sum() b_group_Click_sum = b_group['Click'].sum() print('A group View sum: %s'%(a_group_View_sum)) print('B group View sum: %s'%(b_group_View_sum)) print('A group Click sum: %s'%(a_group_Click_sum)) print('B group Click sum: %s'%(b_group_Click_sum))
A group View sum: 149422.0
B group View sum: 151117.0
A group Click sum: 10423.0
B group Click sum: 12133.0
Дизайн B является более результативным, по сравнению с дизайном A. По обоим показателям наблюдается позитивный эффект. Но… имеют ли наши выводы статистическую значимость?
A-B тест
Рассчитаем средние по каждому показателю; по каждой группе: A и B. Рассчитаем также разницы средних значений.
columns = ['View', 'Click'] obs_diffs = {} for column in columns: view_cont= alldata.loc[alldata['Campaign_Name']=='a campaign'][column].mean() view_test= alldata.loc[alldata['Campaign_Name']=='b campaign'][column].mean() print('Mean of %s "a campaign": %sn' % (column, round(view_cont,3))) print('Mean of %s "b campaign": %sn' % (column, round(view_test,3))) obs_dif_vw= view_test - view_cont obs_diffs[column] = obs_dif_vw # this content is from dsprog.pro print('Diff means of %s : %sn' % (column, round(obs_dif_vw,3))) print("**************")
Mean of View «a campaign»: 4.981
Mean of View «b campaign»: 5.037
Diff means of View : 0.056
Mean of Click «a campaign»: 0.347
Mean of Click «b campaign»: 0.404
Diff means of Click : 0.057
Применим технику бутстрэпа для оценки разности средних значений вариабельности между группами a campaign и b campaign путем многократной генерации случайных выборок и подсчета разности средних значений. Сформируем гистограммы по результатам.
columns = ['View', 'Click'] boxes_data = {} for column in columns: n_iterations = 10000 group_control = alldata[alldata['Campaign_Name'] == 'a campaign'][column].values group_test = alldata[alldata['Campaign_Name'] == 'b campaign'][column].values diffs_viw = np.empty(n_iterations) np.random.seed(200) # this content is from dsprog.pro for i in range(n_iterations): random_indices = np.random.choice(len(group_control), len(group_control), replace=True) sample_control = group_control[random_indices] sample_test = group_test[random_indices] diffs_viw[i] = np.mean(sample_test) - np.mean(sample_control) diffs_view = np.array(diffs_viw) boxes_data[column] = diffs_view low, high = np.percentile(diffs_view, 2.5), np.percentile(diffs_view, 97.5) plt.figure(figsize=(6,5)) plt.xlabel(column + ': proportions of differences', fontsize=15) plt.ylabel(column + ': frequency', fontsize=15) plt.axvline(x= low, color= 'r', linewidth= 2) plt.axvline(x= high, color= 'r', linewidth= 2) plt.hist(diffs_view)
По каждому показателю сделаем сопоставление между p-value и альфа уровнем для принятия либо опровержения нулевой гипотезы.
The p-value for View is: 0.1218
Unable to reject Null Hypothesis, no statistically difference between «a group» and «b group» 0.1218 > α on View
The p-value for Click is: 0.0
Reject Null Hypothesis, statistically significant difference between «a group» and «b group» 0.0 < α on Click
Выводы
По показателю View мы не можем отвергнуть гипотезу 𝐻0. Новая форма дизайна не привнесла статистически значимых изменений на показатель просмотров пользователями страниц web-приложения. Вместе с тем новый дизайн оказал статистически значимое влияние на показатель Click. Таким образом, в целом значительная разница в эффективности между дизайном A и B все же существует.
=====================
Для получения полного контента данной статьи; для сотрудничества с автором, пишите в Телеграм: cryptosensors
Полный контент данной статьи включает файлы/данные:
- файл Jupyter Notebook (ipynb),
- файлы датасетов (csv или xlsx),
- неопубликованные элементы кода, нюансы.
Распространение материалов с dsprog.pro горячо приветствуется (с указанием ссылки на источник).