Пример дизайна теста
https://t.me/datadeepdiveПример дизайна теста для выдуманного сайта по продаже новогодних ёлок.
Менеджер заполнил доку своей идеей и принёс на согласование в отдел тестирований:
Гипотеза. Хотим изменить сортировку по умолчанию. Сейчас у нас товары выстроены от самых дорогих к дешёвым. Хотим поменять порядок. Думаем что из-за этого юзеры не будут пугаться цен и начнут совершать больше покупок.
Варианты. Контрольный вариант (A) -- ничего не меняем. Тестовый вариант (B) -- меняем сортировку по умолчанию, сначала дешёвые товары, потом дорогие.
Ожидания. Думаем, что если юзерам будут доступны дешёвые ёлки с первого взгляда на каталог, они будут чаще совершать покупку и реже отваливаться.
Ограничения. Ограничений нет.
Ты согласовал-а идею и дописываешь доку со своей стороны:
Ключевая метрика. Конверсия в покупку (CR).
Дополнительные метрики. Средний чек (если юзеры станут чаще покупать дешёвые ёлки, мы можем уронить средний чек); Добавление ёлки в корзину (конверсия в покупку -- метрика тяжелая, изменения на ней замерить сложно, поэтому для страховки возьмём CR-cart как прокси-метрику, будем считать, что если CR-cart вырастет, то вероятно, вырастит и CR).
База ключевой метрики и вариативность. Средняя конверсия за последний месяц 4.3%, отклонение 0.3
MDE. Ожидаем увеличения конверсии на 20% от текущего значения.
Валидация MDE. 20% от 4.3% это 0.86. При увеличении базовой конверсии на 20% мы ожидаем повысить конверсию до 5.16%. Наш MDE 0.86 составляет почти 3 отклонения (0.3 х 3 = 0.9). Выглядит оптимистично, но всё ещё реалистично. Оставляем без изменений.
Рассчитываем выборку. Получаем по 9,563 юзеров на каждый вариант:
###### R: ###### > mde <- 0.2 # создаем наш mde > p1 <- 0.043 # создаем базовую конверсию > p2 <- p1 * mde + p1 # считаем целевую конверсию > # считаем размер выборки > power.prop.test(p1 = p1, p2 = p2, sig.level = 0.05, power = 0.8, alternative = 'two.sided') Two-sample comparison of proportions power calculation n = 9563.229 p1 = 0.043 p2 = 0.0516 sig.level = 0.05 power = 0.8 alternative = two.sided NOTE: n is number in *each* group ###### Python: ###### > import statsmodels.stats.api as sms > mde = 0.2 # создаем наш mde > p1 = 0.043 # создаем базовую конверсию > p2 = p1 * mde + p1 # считаем целевую конверсию > # считаем размер выборки > sample_size = sms.NormalIndPower().solve_power( sample_size = sms.proportion_effectsize(p1, p2), alpha = 0.05, power = 0.8, alternative = 'two-sided' ) > print(f'n = {sample_size}') n = 9545.187458147324
Рассчитываем сроки теста. У нас тест на 2 варианта, значит нам нужно прогнать 19,126 юзеров через тест. Средний траффик у нас 4000 человек в день. Юзеров мы прогоним за 5 дней. Но увеличим тест до 7 дней, чтобы задеть выходные и зафиксировать изменение поведения юзеров, если оно там есть.
На практике, раз уж мы увеличиваем продолжительность теста, полезно слегка снизить MDE -- мы всё равно освободимся не раньше недели, но зато немного повысим мощность теста.
Трекинг. В трекинг ничего добавлять не нужно.