Всем привет! Я Ваня Касторнов, продуктовый аналитик Лиги Ставок. На сегодняшний день все вокруг говорят о необходимости проведения а/б тестирования, но зачастую оказывается, что их проводят, не проверяя статистическую значимость, или даже не знают, как их проводить. Здесь не будет абстрактного описания, зачем и как делать а/б тесты, вместо этого я постараюсь развеять туман над тем, какие статистические методы использовать в разных ситуациях, а также приведу примеры скриптов на python, чтобы вы могли сразу ими воспользоваться.  Для кого эта статья: для аналитиков, продактов или любого, кто сам планирует провести аб тест.  Как читать? Я старался учесть последовательность при написании, но на самом деле, это скорее шпаргалка — в любой момент, когда вам нужно провести аб тест, вы можете найти в ней кейс, который подходит для вас, и воспользоваться им, в конце есть ссылка на сводную схему.  Пара слов, и начнем. Пока я писал эту статью, я старался не использовать много научной терминологии, чтобы не распугать вас, но где‑то она встречается, извините за это…))  Что ж, начнем… У нас есть две выборки, которые мы получили рандомным путем. Первое, что нам нужно сделать, чтобы начать эксперимент, это определить метрику (или метрики), на основании которой мы будем принимать решение: то, на основании чего, построена сама гипотеза. Выбор статистического метода в том числе зависит от типа метрики, на которую мы будем смотреть. Мы поделим метрики на три типа: Количественные (количество ставок или заказов). Пропорционные или качественные (конверсия в покупку, CTR) Соотношения (рентабельность или отношение открытых продуктовых карточек к количеству покупок). С каждым типом метрик — свой определенный подход, так как наибольшее количество А/Б тестов проводят с метриками пропорций, то с него и начнем, он же и самый простой. Тут все просто, наилучший метод чтобы проверить статистическую значимость изменения для пропорций это метод Хи‑Квадрат. Но перед тем, как его проводить, стоит проверить размер тестовой группы для желаемого минимального статистически значимого изменения. Это можно сделать, используя один из инструментов в интернете, например, этот или с помощью библиотеки statsmodels.stats через python, вот пример кода: В обоих вариантах вам необходимо указать базовый уровень конверсии, минимальное значение для обнаружения изменения, уровень a (процент раз, когда разница будет обнаружена при условии, что ее нет) и уровень мощности (процент раз, когда будет обнаружено минимальное значение изменения, если оно существует). Обнаружив необходимый размер выборки, мы можем приступать к самому тесту. Опять же, в интернете полно сайтов с онлайн‑калькуляторами, которые позволят это сделать, например, вот этот. Если же вы решите провести тест используя python, то вот пример скрипта, который позволит это сделать. Вторые по популярности аб тесты проходят с количественными метриками, примерами таких метрик могут быть: количество ставок, длина сессии и тд. При анализе количественных метрик важно выбрать правильный метод проверки статистической значимости. Так как мы выбрали рандомизированный метод сплитования, то скорее всего мы столкнемся с высоким уровнем дисперсии (разности) данных, что будет негативно влиять на определение значимости результатов, поэтому я рекомендую использовать CUPED (Controlled pre‑post experimental design) — это статистический метод, который все чаще используется в А/Б тестировании для повышения точности полученных результатов. Таким образом, мы сможем нивелировать уровень дисперсии, сезонные изменения, маркетинговые акции и другие факторы. Подробнее про метод вы можете почитать тут или в оригинальной статье. Для того, чтобы использовать cuped, нам потребуются набор данных со значением метрик в предтестовый период и само значение в момент теста. Для того, чтобы преобразовать данные вот пример скрипта: После того, как мы получили данные, стоит оценить размер выборки, тут есть два варианта. Если выборка большая… То нужно посмотреть на нормальность распределения данных, в целом все просто, проверить нормальность распределения поможет вот этот скрипт, который использует тест Шапиро‑Уилка, он подойдет в большинстве случаев: Итак, распределение получилось нормальным, что же дальше.. Дальше мы можем провести самый используемый метод проверки отсутствия нулевой гипотезы, а именно t‑test, наиболее известным является т‑критерий стъюдента, он также подойдет, если же между группами осталась неравная дисперсия, то лучше подойдет т‑критерий Уэлча, в целом может использовать его всегда не будет ошибкой, но вы можете столкнуться с меньшим уровнем значимости. Оба теста удобно проводить, используя библиотеку scipy.stats, вот примеры запросов: Но бывает и так, что распределение данных не соответствует нормальному, что же тогда? В этом случае лучше всего подходит U‑test Манна‑Уитни, В отличие от параметрических тестов, таких как t‑тест Стьюдента или t‑test Уэлча, U‑test Манна‑Уитни не делает никаких предположений о форме базового распределения. Для того, чтобы его провести, мы можем обратится к той же библиотеке scipy.stats: Что делать, если размер выборки нормальный, мы разобрались, но бывает, когда данных очень мало, тут на помощь приходит bootstrap. Основная идея bootstrap заключается в многократной выборке с заменой из исходных данных для создания большого количества «выборок». Каждая выборка похожа на исходную выборку, но имеет немного другие значения из‑за случайного подставления, подробнее можно узнать в этой статье, а пример скрипта выглядит так: Фух, кажется с количественными метриками все… В соотношениях два числовых значения, чаще всего числитель — это количество выполненных действий, а знаменатель — это количество пользователей, например, количество ставок на пользователей, которые открывали карточки событий, или же количество открытых карточек на количество просмотренных. Бывает, что суть гипотезы именно в изменении подобных метрик, что ж, тут мы будем ориентироваться на два варианта проверки статистической значимости, которые основываются на размерах выборки. Перво‑наперво я рекомендую так же использовать один из вариантов сокращения дисперсии между данными, CUPED в данном случае не подойдет, так как это метод, который помогает уменьшить ошибки в данных, контролируя одну переменную, которая сильно связана с исследуемой переменной. Однако, если причина изменения исследуемой переменной является тем, имеет ли место какое‑то воздействие (например, показ обучающего баннера или получение фрибета (бесплатной ставки)), то CUPED не может использоваться, так как не существует других факторов, которые можно контролировать. В этом случае лучше использовать метод Diff‑in‑diff, который позволяет учитывать другие факторы, влияющие на результаты, и исследовать эффект воздействия на исследуемую переменную. Чтобы использовать diff in diff, можно воспользоваться скриптом, который указан ниже, структура данных должна быть следующей: каждая строка соответствует одному участнику теста, а столбцы представляют различные переменные, например: ID участника, группа A/B‑теста, временной период, зависимая переменная: Так, данные в порядке, переходим к проверке. Предположим, что выборка имеет внушительный размер, тогда нам нужно всего‑то провести t‑test, но сперва стоит взглянуть еще раз на дисперсию. Например, наша метрика это CTR, клики и просмотры являются случайными величинами, и когда мы объединяем их в одну метрику CTR, они будут иметь совместное распределение. Кроме того, если наша рандомизация основана на user_id, один пользователь может генерировать несколько просмотров, так что просмотры не являются независимыми друг от друга. Лучше использовать дельта‑метод для аппроксимации дисперсии соотношений и после этого проводить t‑test, в помощь приходит библиотека scipy.stats. Скрипт может выглядеть следующим образом. Ну и последний метод, который мы рассмотрим, который стоит применять если размер выборки маленький. В таком случае bootstrap будет также актуален. Но так как мы пытаемся анализировать метрику, соотношения и наблюдения в данных могут быть независимыми, то больше подойдет блочный bootstrap. В обычном bootstrap данные берутся из исходной выборки с заменой, в блочном данные берутся группами (или блоками). Это нужно потому, что мы хотим учесть структуру зависимости в данных. В конце проведем уже известным нам t‑test. Скрипт похож на обычный bootstrap: Важный критерий после проведения тестов статистической значимости — это проверка мощности. Эксперимент с низкой мощностью будет страдать от высокой частоты ложных отрицательных результатов (ошибка второго типа). Размер эффекта обычно представляет собой разницу в средних между контрольной и тестовой группами, деленную на стандартное отклонение. Чтобы проверить мощность после получения результатов, можно воспользоваться TTestIndPower из библиотеки statsmodels, а скрипт может выглядеть следующим образом: В итоге, чтобы провести успешный A/B тест, необходимо выбрать метод анализа, который подходит для конкретных метрик и размера выборки, а также учитывать все факторы, которые могут повлиять на результаты. Важно следить за мощностью эксперимента после его проведения, чтобы убедиться, что результаты являются значимыми. Для более простого восприятия я добавил в Miro общую схему, которая будет работать как навигатор выбора стат метода для вашего теста. Я надеюсь, что эта статья поможет вам в проведении А\Б тестов и увеличит значимость принимаемых решений, что положительно отразится на вашем продукте и личном прогрессе. Подписывайтесь на мой телеграм канал, где я рассказываю как улучшать продукты на основе анализа данных, а также добавляйте статью в избранное, и до скорой встречи!  Head of Product Analytics