You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python hashlib对客户ID做哈希实现AB测试均等分箱

基于hashlib实现稳定AB组分箱的方案

这种哈希分箱的核心优势是确定性运算,相同输入永远得到相同输出,分箱结果可复现,不需要维护随机种子,同一个用户在同个实验中每次运行都会分到同一个分箱,比随机打乱的方案更适合需要回溯的实验场景。

完整实现代码

import pandas as pd
import hashlib

# 你原来的测试数据
df = pd.DataFrame({'exp_variant_id'  :  [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
'test_control'  :  ['control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'control', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test', 'test'],
'metric_name'  :  ['order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt', 'order_qnt'],
'metric_value'  :  [234, 1, 3234, 1, 44, 1, 1, 22, 234, 22, 33, 234, 2, 22, 3, 2, 22, 432, 55, 50, 45, 40, 35, 30, 24, 20, 16, 12, 8, 4, 5, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51, 55, 59, 63, 67, 71, 75, 79],
'user_client_id'  :  [21118, 20905444, 56313312, 10738744, 103594830, 83751548, 93299328, 16483186, 130606918, 48995246, 137653680, 63458228, 6968570, 36369312, 13743160, 10331626, 5928990, 50640476, 58021806, 34024250, 4354098, 32314326, 51335518, 31380850, 3710088, 147258556, 6087272, 11858930, 7993504, 100529398, 70127992, 34863920, 18179366, 10651330, 7390348, 18208032, 63247112, 136361832, 36873330, 64035326, 17854770, 106190670, 85201466, 64841914, 116933396, 11482546, 43565902, 112231512, 150755048, 14561480]})

# 自定义参数:每箱用户数,可按需求修改
CHUNK_SIZE = 5
# 自定义盐值:不同实验用不同盐,避免不同实验分箱逻辑重合导致偏差
SALT = 'ab_test_bin_202406'

# 哈希转换辅助函数:把输入值转成可排序的大整数
def get_hash_int(input_val):
    hash_obj = hashlib.md5(f"{SALT}_{str(input_val)}".encode('utf-8'))
    # 把16进制哈希值转成整数
    return int(hash_obj.hexdigest(), 16)

# 存储每个用户对应的分箱ID
user_bin_map = {}

# 按AB组分别分箱
for variant in df['exp_variant_id'].unique():
    # 取当前组的唯一用户列表
    variant_users = df[df['exp_variant_id'] == variant]['user_client_id'].unique()
    # 给每个用户计算哈希值,按哈希值排序实现稳定打乱
    users_with_hash = [(user, get_hash_int(user)) for user in variant_users]
    users_with_hash.sort(key=lambda x: x[1])
    sorted_users = [item[0] for item in users_with_hash]
    # 按指定大小切分分箱
    for bin_id, start_idx in enumerate(range(0, len(sorted_users), CHUNK_SIZE), 1):
        current_bin_users = sorted_users[start_idx: start_idx + CHUNK_SIZE]
        for user in current_bin_users:
            user_bin_map[user] = bin_id

# 把分箱ID映射回原DataFrame
df['bin_id'] = df['user_client_id'].map(user_bin_map)

# 验证分箱结果
print(df.groupby(['exp_variant_id', 'bin_id'])['user_client_id'].nunique())

注意事项

  • 如果担心MD5碰撞,把hashlib.md5替换成hashlib.sha256即可,逻辑完全一致
  • 只要盐值和每箱大小不变,同一个用户的分箱结果永远固定,不会因为重跑代码、新增用户导致历史分箱变动
  • 哈希排序的均匀性有保证,分箱用户数差异和随机打乱的效果一致

内容的提问来源于stack exchange,提问作者bigsbi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 12:54:04