如何生成匹配90万用户指标的分布以用于AA/AB测试样本生成?
分布定性判断
从你提供的统计量和样本分布来看,这是右偏厚尾的混合分布:
- 均值(483)远高于中位数(125),数据向右侧严重偏移
- 最大值(151074)远超75分位数(421),存在大量极端大值,属于厚尾特征
- 结合0值存在的情况,该分布由两部分构成:一部分是取值为0的离散样本,另一部分是右偏的连续分布(类似对数正态、截断帕累托的特征)
模拟样本生成方案(满足0-100区间精准匹配)
不用强行拟合整体复杂分布,针对你的需求,采用分区间复刻+尾部随机生成的方法即可:
1. 精准复刻0-100区间分布
- 从95万原数据中筛选出0-100区间的所有样本,统计该区间内每个取值(或分箱)的频率占比
- 生成模拟样本时,严格按照这个频率分布随机抽取对应数量的样本,确保0-100区间和原分布完全匹配
2. 尾部(>100)样本简化生成
尾部允许随机,可基于原数据尾部特征快速生成:
- 统计原数据中>100样本的占比,保证模拟样本的尾部占比和原数据一致
- 可选两种生成方式:
- 直接对原数据的尾部样本进行重采样(简单高效,保留原尾部特征)
- 用对数正态分布拟合原尾部数据(只拟合>100部分,难度低),生成符合尾部大致特征的随机数
3. 组合与验证
- 将0-100区间的精准样本和尾部随机样本按原比例混合,打乱顺序得到模拟数据集
- 验证0-100区间的频率分布是否与原数据一致,同时确保整体统计量(均值、分位数)贴近原数据,满足AA/AB测试要求
Python代码示例
import pandas as pd import numpy as np from scipy import stats # 假设原数据存储在df的'metric'列 # 1. 提取0-100区间的分布特征 low_mask = (df['metric'] >= 0) & (df['metric'] <= 100) low_samples = df.loc[low_mask, 'metric'] low_freq = low_samples.value_counts(normalize=True) low_sample_size = int(len(df) * low_mask.mean()) # 生成0-100区间模拟样本 sim_low = np.random.choice(low_freq.index, size=low_sample_size, p=low_freq.values) # 2. 生成尾部模拟样本 high_mask = df['metric'] > 100 high_sample_size = len(df) - low_sample_size # 方法1:直接重采样原尾部样本(推荐) high_samples = df.loc[high_mask, 'metric'] sim_high = np.random.choice(high_samples, size=high_sample_size, replace=True) # 方法2:对数正态拟合尾部(可选) # log_high = np.log(high_samples) # mu, sigma = stats.norm.fit(log_high) # sim_high = np.exp(np.random.normal(mu, sigma, size=high_sample_size)) # 3. 组合并打乱样本 simulated_data = np.concatenate([sim_low, sim_high]) np.random.shuffle(simulated_data) # 验证0-100区间匹配度 sim_low_counts = pd.Series(simulated_data[(simulated_data>=0)&(simulated_data<=100)]).value_counts(normalize=True) print("0-100区间分布匹配度:", np.allclose(sim_low_counts.sort_index(), low_freq.sort_index(), rtol=1e-3))
内容的提问来源于stack exchange,提问作者Roman Stasiuk
相关产品推荐
相关产品推荐

