Как правильно разбить существующие магазины компании на две группы для A/B-теста?

Ответ

При разбиении существующих магазинов на тестовую и контрольную группы для A/B-теста моя главная цель — сделать группы максимально похожими по всем значимым параметрам, кроме внедряемого изменения. Я использую стратифицированную рандомизацию.

Практический подход (на Python):

  1. Определяю ключевые страты (признаки): Это метрики, которые сильно влияют на целевую переменную (например, выручку). Обычно это:

    • Географический регион / тип города.
    • Формат и площадь магазина.
    • Историческая средняя выручка за последний квартал.
    • Трафик (среднее количество чеков).
  2. Создаю страты и выполняю разбиение:

    import pandas as pd
    import numpy as np
    from sklearn.model_selection import train_test_split
    
    # df - DataFrame с данными магазинов
    # Создаю категориальную переменную 'strata', комбинируя ключевые признаки
    df['strata'] = (
        df['region'].astype(str) + '_' + 
        pd.qcut(df['historical_revenue'], q=4, labels=['q1','q2','q3','q4']).astype(str)
    )
    
    # Стратифицированное разбиение. test_size=0.5 для двух равных групп.
    group_a, group_b = train_test_split(
        df,
        test_size=0.5,
        stratify=df['strata'],
        random_state=42 # для воспроизводимости
    )
  3. Проверяю баланс: После разбиения обязательно проверяю, что распределение ключевых метрик (средняя выручка, медианная площадь) между группами статистически неразличимо (например, с помощью t-теста или визуализации). Если дисбаланс есть, повторяю разбиение.

Почему не простая случайная выборка? Прямой рандомизации недостаточно для магазинов, так как они сильно различаются. Стратификация гарантирует, что в каждой группе будет пропорциональное количество, например, маленьких магазинов в регионах и крупных в столице, что делает сравнение честным.

Ответ 18+ 🔞

Давай разберем эту тему, как будто я тебе на кухне объясняю, пока чайник кипит. Представь, что у тебя есть куча магазинов — все разные, как люди. Один в центре, блядь, золотое дно, другой на окраине, где только кошки шляются. И тебе нужно их поделить на две команды для какого-то нового эксперимента, типа новой выкладки товара или скидочной хуйни.

Так вот, если ты просто рандомно, с закрытыми глазами, тыкаешь пальцем — «ты в группу А, ты в Б» — это пиздец как нечестно. Может так выйти, что в одну группу попадут все жирные магазины, а в другую — одни дыры. И потом ты будешь смотреть на результаты и охуевать: «Ну бля, новая выкладка работает огонь!» А на самом деле она просто в богатых магазинах тестировалась, ебать мои старые костыли. Доверия к такому тесту — ноль ебать.

Поэтому умные люди придумали стратифицированную рандомизацию. Суть проще пареной репы, хоть слово и страшное.

Ты сначала определяешь, по каким признакам магазины друг от друга реально отличаются. Это как страты, или слои. Обычно это:

  • Регион (столица, областной центр, дыра).
  • Размер и формат (гипермаркет, супермаркет, ларек).
  • Историческая выручка (сколько денег гребали до эксперимента).
  • Трафик (сколько людей вообще заходит).

Потом ты не просто мешаешь всех в кучу, а действуешь, как хитрая жопа. Ты берешь, например, все столичные гипермаркеты с высокой выручкой — это один слой. И из этого слоя ты поровну раскидываешь магазины в группу А и группу Б. Потом берешь областные супермаркеты со средним доходом — и тоже поровну делишь. И так далее, по всем типам.

Вот тебе как это на Питоне выглядит, если в двух словах:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

# df - это твоя таблица со всеми магазинами
# Создаём страты: комбинируем регион и уровень выручки (разбили её на 4 квартеля)
df['strata'] = (
    df['region'].astype(str) + '_' +
    pd.qcut(df['historical_revenue'], q=4, labels=['q1','q2','q3','q4']).astype(str)
)

# А теперь волшебство: стратифицированное разбиение пополам
group_a, group_b = train_test_split(
    df,
    test_size=0.5,  # Половина на половину
    stratify=df['strata'],  # Вот эта самая стратификация
    random_state=42  # Чтобы при повторении всё было одинаково, а не как попало
)

После этого самое главное — не расслабляться. Надо проверить, не накосячил ли ты. Сравниваешь среднюю выручку, площадь и прочее между группами А и Б. Если они статистически неотличимы — красота, ёпта. Если же в одной группе средняя выручка зашкаливает, а в другой — хуй с горы, то где-то ты просрал страты и нужно переделывать.

Короче, смысл в чём: простая случайная выборка для магазинов — это как играть в русскую рулетку с автоматом Калашникова. Стратификация же гарантирует, что в каждой группе будет одинаковый «коктейль» из разных типов точек. Только тогда результат A/B-теста будет хоть сколько-нибудь правдивым, а не просто красивой, но пиздопроебибной картинкой в отчете для начальства.