直接用ttest_ind检验转化率差异是错误的,因其假设数据服从正态分布且为连续变量,而转化率是二项分布的0/1离散数据;应改用binom_test或proportions_ztest。

用 scipy.stats.ttest_ind 判断两组转化率是否有显著差异
直接拿 A/B 两组用户转化率(比如点击率、下单率)去跑 ttest_ind 是错的——它默认数据服从正态分布且是连续变量,而转化率本质是二项分布、样本是 0/1。强行用会低估 p 值,容易误判“显著”。
正确做法是:把每组看作 n 次伯努利试验,用 scipy.stats.binom_test 或更稳健的 statsmodels.stats.proportion.proportions_ztest。后者在样本量 ≥50 且成功/失败数都 ≥5 时近似可靠,速度也比精确检验快。
-
binom_test:适合小样本(比如每组 -
proportions_ztest:推荐日常使用,传入count(成功数)和nobs(总样本数)两个数组 - 别传均值或比率本身——
proportions_ztest要的是原始计数,不是[0.12, 0.15]
为什么 chi2_contingency 比 z 检验更通用
当你要同时比较多个版本(A/B/C)、或多维分层(比如按新老用户+设备类型交叉)时,z 检验就撑不住了。scipy.stats.chi2_contingency 接收二维列联表,天然支持多组多分类场景,且不依赖正态近似。
注意它返回的卡方统计量对样本量敏感:小样本下期望频数 scipy.stats.fisher_exact,仅限 2×2 表)。
立即学习“Python免费学习笔记(深入)”;
- 构造输入时用
np.array([[a_success, a_fail], [b_success, b_fail]]),别搞反行列顺序 - p 值显著 ≠ 效果大——卡方检验只回答“是否独立”,不回答“差多少”,得额外算效应量(如 Cramer’s V)
- 如果做多重比较(比如 5 个按钮样式),p 值要校正,否则假阳性飙升;
statsmodels.stats.multitest.multipletests可选'bonferroni'或'fdr_bh'
真实业务中漏掉的三个关键前提
A/B 测试的统计结论成立,依赖三个常被跳过的前提:随机性、独立性、稳定性。缺一个,p 值再小也没意义。
- 随机性没保障?比如流量按 user_id % 10 分流,但 user_id 本身有时间趋势(新用户集中涌入),A 组天然含更多新客——此时组间差异可能来自分流逻辑,而非实验干预
- 独立性被破坏?比如同一用户在 A 组看到广告后,又在 B 组重复出现(未去重),他的两次行为不是独立观测,标准误差会被低估
- 稳定性不足?实验只跑了 2 天,但业务有强周周期(周末转化率高 30%),而 A 组撞上周末、B 组撞上工作日——这种混杂变量会让结论失效
上线前必须检查的代码细节
写完检验脚本别急着跑,这几个地方一错,结果全废:
- 用
proportions_ztest时,确认count是整数——如果从数据库取的是浮点型转化率,得先乘nobs再round(),否则报ValueError: counts must be integers - 卡方检验前,检查列联表里有没有全零行/列,
chi2_contingency遇到会直接抛ZeroDivisionError - 别在实验中途看 p 值——每看一次都相当于一次假设检验,累积错误率爆炸;真要监控,得用序贯检验(如
alpha-spending)或固定终点设计










