Вы сейчас просматриваете A-B тест. Еще раз. Тестируем новый дизайн.

A-B тест. Еще раз. Тестируем новый дизайн.

Автор: Евгений Бодягин, 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_IDCampaign_NameViewClick
01a campaign4.00.0
12b campaign12.00.0
23a campaign1.00.0
34a campaign5.00.0
45a campaign8.00.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 горячо приветствуется (с указанием ссылки на источник).