← Back to list

Как разделить “сплитануть” пользователей(user_id) на группы для А/Б теста.

В данной статье я бы хотел показать как можно разделить правильно пользователей на группы для проведения А/Б теста и получить…

Aziz · 2023-05-11 14:40 · 0 claps · 1.2 min read
#split-testing #ab-split-testing #сплит #сплит-трафика #абтест
Open on Medium ↗

Как разделить “сплитануть” пользователей(user_id) на группы для А/Б теста.

В данной статье я бы хотел показать как можно разделить правильно пользователей на группы для проведения А/Б теста и получить репрезентативную выборку для сравнения. Не буду разбрасываться теорией сразу перейду к примерам, чтобы вы могли взять и использовать.

Сплит с помощью SQL:

SELECT  conv(substr(md5(concat(USER_ID, 'gywrnbf132')), 1, 12), 16, 10)%6 as bucket

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

%6 это количество бакетов которые мы хотим получить на выходе. Их можно также обьеденить в группы:

(CASE WHEN bucket in (1,2) then 'A' 
WHEN bucket in (3,4) then 'B'
WHEN bucket in (5,6) then 'C'
ELSE null END)

Сплит с помощью Python:

import hashlib
import pandas as pd

# Определяем соль :
salt= 'OkMdZa18pfr8m5sy2IL52pW9ol2EpLekgakJAIZFBbgZ'

# Функция которая будет делить на группы:
def funnel_user(base_traffic_split, test_seed, user_id):
 test_id = hashlib.md5(test_seed.encode('ascii') + str(user_id).encode('ascii')).hexdigest()
 bits = bin(int(test_id, 16))[3:]
 r = sum([int(bit)*(0.5**(i+1)) for i, bit in enumerate(bits)])
 if r < base_traffic_split:
 return 'A'
 else:
 return 'B'

Проверяем: 
new_split = [] # Сюда записываем группу
new_users= [] # Тут будет user_id

# df это ДатаФрейм с нашими user_id

for i in df['user_id']:
  x = funnel_user(base_traffic_split= 0.5, test_seed=salt, user_id = i)
  new_users.append(i)
  new_split.append(x)

# Получаем Дата Фрейм с нашим сплитом
df_with_groups = pd.DataFrame({'user_id': new_users, 'ab_new_group': new_split})
# Следующий пример на основе библиотеки разработанной коллегами из FaceBook(Meta)
from planout.experiment import SimpleExperiment
from planout.ops.random import *

salt= 'OkMdZa18pfr8m5sy2IL52pW9ol2EpLekgakJAIZFBbgZ'

class MyExpiriment(SimpleExperiment):
  def assign(self, params, userid):
    self.salt = salt
    params.test_group = UniformChoice(choices=['A', 'B'],
    weights=[0.3, 0.7], unit=userid)

new_split = []
new_users= []

# experiment objects include all input data

for i in ab_test['user_pseudo_id']:  
    new_users.append(i)
    new_split.append(MyExpiriment(userid=i).get('test_group'))  

df_with_groups = pd.DataFrame({'user_id': new_users, 'ab_new_group': new_split})

Надеюсь кому-то это пригодится и буду рад вопросам, комментариям. Всем хороших А/Б тестов


메타데이터
post_id
118c4cabbdec
slug
как-разделить-сплитануть-пользователей-user-id-на-группы-для-а-б-теста-118c4cabbdec
url
https://medium.com/@azizbek_performance/%D0%BA%D0%B0%D0%BA-%D1%80%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D1%8C-%D1%81%D0%BF%D0%BB%D0%B8%D1%82%D0%B0%D0%BD%D1%83%D1%82%D1%8C-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9-user-id-%D0%BD%D0%B0-%D0%B3%D1%80%D1%83%D0%BF%D0%BF%D1%8B-%D0%B4%D0%BB%D1%8F-%D0%B0-%D0%B1-%D1%82%D0%B5%D1%81%D1%82%D0%B0-118c4cabbdec
canonical_url
https://medium.com/@azizbek_performance/%D0%BA%D0%B0%D0%BA-%D1%80%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D1%8C-%D1%81%D0%BF%D0%BB%D0%B8%D1%82%D0%B0%D0%BD%D1%83%D1%82%D1%8C-%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D0%B5%D0%B9-user-id-%D0%BD%D0%B0-%D0%B3%D1%80%D1%83%D0%BF%D0%BF%D1%8B-%D0%B4%D0%BB%D1%8F-%D0%B0-%D0%B1-%D1%82%D0%B5%D1%81%D1%82%D0%B0-118c4cabbdec
author_url
https://medium.com/@azizbek_performance
status
ok
fetched_at
2026-07-25 17:14:12