A/B検定有意性カルキュレーター
A/Bテストの訪問者数とコンバージョン数を入力するだけで、その差が統計的に有意かどうかを判定する無料ツール。二比率のz検定に基づき、p値、z値、95%信頼区間、2つのバリアント間の相対リフト(コンバージョン率の変化率)を同時に算出し、結果が偶然によるものか確からしいものかをすぐに確認できる。
A/B検定有意性カルキュレーター
各バリアントの訪問者数とコンバージョン数を入力して、差が実際のものかノイズだけかを確認してください。
結果
統計的に有意
差は選択した信頼水準での偶然によるものである可能性は低いです。
Chance this gap is just luck — lower is stronger.
How far apart the two rates are, in standard errors.
The likely range for the true difference.
ドキュメンテーション
1分でわかるA/Bテスト
ボタン、見出し、またはチェックアウトフローを変更しました。バージョンAは古いもの、バージョンBは新しいものです。Bの方が見た目は良さそうです — 訪問者の15%がコンバージョンしたのに対し、Aは10%です。しかし、この差は単なる運かもしれません。コインを10回投げて7回表が出るのと同じように。
このカルキュレーターはまさにそれに答えます。各バージョンを見た人数とコンバージョン数を入力すると、測定した差が実際なのかランダムノイズなのかの確率を教えてくれます。その確率が高ければ、勝者がいます。そうでなければ、テストを続行します。
注目する数値はp値です:2つのバージョンが実際に同じだった場合に、少なくともこのくらい大きな差が見られる確率。小さいp値(たとえば0.05未満)は「これは運で起こることはめったにないので、差はおそらく実際のものです」を意味します。
使い方
- 訪問者数 — 各バージョンを表示されたユニークユーザーの数。
- コンバージョン数 — それらのうち、気になることをした人数(購入、サインアップ、クリック)。
- 信頼水準 — 勝者と判定する前にどの程度確信したいか。95%は業界標準。
- 仮説 — 両側は「BはAと異なるか?」と尋ねます(より安全、デフォルト);片側は「BはAより優れているか?」とだけ尋ねます(より敏感ですが、テスト前に方向を決定する必要があります)。
結果はリアルタイムで更新され、入力はページURLに保存されるため、結果をブックマークまたは共有できます。リセットはフォームをクリア;サンプルデータを読み込むは解答例を入力します。
解答例
| 訪問者数 | コンバージョン | レート | |
|---|---|---|---|
| A(対照) | 1,000 | 100 | 10.0% |
| B(変動) | 1,000 | 150 | 15.0% |
これは5パーセントポイントの絶対リフト、+50%の相対リフトです。カルキュレーターはおよそ0.0007のp値を返します — 0.05未満 — したがって95%信頼度で結果は統計的に有意です。大まかに言うと、2つのバージョンが本当に同じだった場合、このくらい大きな差は1000回のテストのうち1回未満で見られるでしょう。
数学(二比率z検定)
背後にあるのは標準的な二比率z検定で、入門統計で教えられ、主流のA/Bテストツールで使用されているのと同じテストです。
-
各グループのコンバージョン率:
ここではコンバージョン数、は訪問者数です。
-
統合レート、(帰無仮説の場合)両グループが1つの真のレートを共有していると仮定:
-
差の標準誤差:
-
z値 — 2つのレートが標準誤差でどれだけ離れているか:
-
p値は標準正規分布から来ます。両側:。片側:。
-
有意なのはのとき、ここで(95%で0.05)。
カルキュレーターはまた差の信頼区間を報告し、非統合標準誤差で計算されます:真の差の妥当な範囲。その区間が0を除外する場合、結果は有意です。
95%信頼度で、±1.96を超えるz(陰影付きの尾部、面積の5%)は有意と見なされます。
結果を正直に読む
- 統計的有意性はビジネス上の有意性ではありません。 0.1%のリフトは統計的に実際でも、配備する価値がないかもしれません。
- 覗き見て早期に停止しないでください。 p値を毎日チェックして0.05未満に低下した瞬間に停止すると、偽陽性率が増加します。事前にサンプルサイズを決定してテストを完了させてください。
- サンプルサイズの経験則に注意してください。 正規近似は各グループが少なくとも約10コンバージョンかつ約10非コンバージョンを持つ場合に信頼できます。小さな数字では、結果を方向性のみとして扱ってください。
- 信頼度≠Bが優れている確率。 95%信頼水準は、手順が長期的に最大5%の時間間違っていることを意味します — これは「Bが勝つ95%の確率」ではなく、頻度主義者の声明です。
- 1つのテスト、1つのメトリック。 多くのメトリックまたはバリアントを一度にテストすると、偶然の機会が増加します。それを修正する(例:ボンフェローニ)か、テストを決定する単一のメトリックを事前登録してください。
自分で計算する
各スニペットは上記の例の両側p値を計算します。
1=2*(1-NORM.S.DIST(
2 (B2/A2 - B1/A1) /
3 SQRT(((B1+B2)/(A1+A2))*(1-(B1+B2)/(A1+A2))*(1/A1+1/A2)),
4 TRUE))
5' A1,B1 = control visitors, conversions ; A2,B2 = variation visitors, conversions
61from math import sqrt, erf
2
3def ab_pvalue(n1, x1, n2, x2, two_sided=True):
4 p1, p2 = x1 / n1, x2 / n2
5 p = (x1 + x2) / (n1 + n2)
6 se = sqrt(p * (1 - p) * (1 / n1 + 1 / n2))
7 z = (p2 - p1) / se
8 phi = lambda v: 0.5 * (1 + erf(v / sqrt(2))) # standard normal CDF
9 return 2 * (1 - phi(abs(z))) if two_sided else 1 - phi(z)
10
11print(ab_pvalue(1000, 100, 1000, 150)) # ~0.00072
121// erf via Abramowitz & Stegun 7.1.26
2function erf(x) {
3 const s = x < 0 ? -1 : 1;
4 x = Math.abs(x);
5 const t = 1 / (1 + 0.3275911 * x);
6 const y = 1 - ((((1.061405429 * t - 1.453152027) * t + 1.421413741) * t
7 - 0.284496736) * t + 0.254829592) * t * Math.exp(-x * x);
8 return s * y;
9}
10const phi = z => 0.5 * (1 + erf(z / Math.SQRT2));
11
12function abPValue(n1, x1, n2, x2, twoSided = true) {
13 const p1 = x1 / n1, p2 = x2 / n2, p = (x1 + x2) / (n1 + n2);
14 const se = Math.sqrt(p * (1 - p) * (1 / n1 + 1 / n2));
15 const z = (p2 - p1) / se;
16 return twoSided ? 2 * (1 - phi(Math.abs(z))) : 1 - phi(z);
17}
18console.log(abPValue(1000, 100, 1000, 150)); // ~0.00072
191public static double abPValue(int n1, int x1, int n2, int x2) {
2 double p1 = (double) x1 / n1, p2 = (double) x2 / n2;
3 double p = (double) (x1 + x2) / (n1 + n2);
4 double se = Math.sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2));
5 double z = (p2 - p1) / se;
6 // Phi via the error function; erf approximated (A&S 7.1.26) separately.
7 double phi = 0.5 * (1 + erf(Math.abs(z) / Math.sqrt(2)));
8 return 2 * (1 - phi);
9}
101static double AbPValue(int n1, int x1, int n2, int x2) {
2 double p1 = (double)x1 / n1, p2 = (double)x2 / n2;
3 double p = (double)(x1 + x2) / (n1 + n2);
4 double se = Math.Sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2));
5 double z = (p2 - p1) / se;
6 double phi = 0.5 * (1 + Erf(Math.Abs(z) / Math.Sqrt(2)));
7 return 2 * (1 - phi);
8}
91#include <cmath>
2
3double ab_pvalue(int n1, int x1, int n2, int x2) {
4 double p1 = (double)x1 / n1, p2 = (double)x2 / n2;
5 double p = (double)(x1 + x2) / (n1 + n2);
6 double se = std::sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2));
7 double z = (p2 - p1) / se;
8 double phi = 0.5 * (1 + std::erf(std::fabs(z) / std::sqrt(2.0)));
9 return 2 * (1 - phi);
10}
111import "math"
2
3func abPValue(n1, x1, n2, x2 float64) float64 {
4 p1, p2 := x1/n1, x2/n2
5 p := (x1 + x2) / (n1 + n2)
6 se := math.Sqrt(p * (1 - p) * (1/n1 + 1/n2))
7 z := (p2 - p1) / se
8 phi := 0.5 * (1 + math.Erf(math.Abs(z)/math.Sqrt2))
9 return 2 * (1 - phi)
10}
111// erf from the `libm` crate; std has no erf.
2fn ab_pvalue(n1: f64, x1: f64, n2: f64, x2: f64) -> f64 {
3 let (p1, p2) = (x1 / n1, x2 / n2);
4 let p = (x1 + x2) / (n1 + n2);
5 let se = (p * (1.0 - p) * (1.0 / n1 + 1.0 / n2)).sqrt();
6 let z = (p2 - p1) / se;
7 let phi = 0.5 * (1.0 + libm::erf(z.abs() / 2f64.sqrt()));
8 2.0 * (1.0 - phi)
9}
101function ab_pvalue($n1, $x1, $n2, $x2) {
2 $p1 = $x1 / $n1; $p2 = $x2 / $n2;
3 $p = ($x1 + $x2) / ($n1 + $n2);
4 $se = sqrt($p * (1 - $p) * (1 / $n1 + 1 / $n2));
5 $z = ($p2 - $p1) / $se;
6 $phi = 0.5 * (1 + erf(abs($z) / sqrt(2)));
7 return 2 * (1 - $phi);
8}
91def ab_pvalue(n1, x1, n2, x2)
2 p1, p2 = x1.to_f / n1, x2.to_f / n2
3 p = (x1 + x2).to_f / (n1 + n2)
4 se = Math.sqrt(p * (1 - p) * (1.0 / n1 + 1.0 / n2))
5 z = (p2 - p1) / se
6 phi = 0.5 * (1 + Math.erf(z.abs / Math.sqrt(2)))
7 2 * (1 - phi)
8end
91# R has this built in: prop.test does the whole thing.
2prop.test(c(100, 150), c(1000, 1000), correct = FALSE)$p.value # ~0.00072
3よくある質問
どのくらいのサンプルサイズが必要ですか? 意味のあるリフトが検出可能になるだけの十分なもの。最低限、各バリアントあたり数百のコンバージョンを目指してください;ベースラインレートと検出する価値のある最小リフトで専用のサンプルサイズカルキュレーターを使用してください。
両側それとも片側? 改善のみを気にするための確かな事前コミットした理由がない限り、両側を使用してください。片側はあなたの感度を2倍にしますが、Bがより悪いことに反応することを禁じます。
カルキュレーターが信頼区間を表示するのはなぜですか? 真の差の妥当な範囲を示しており、単なるはい/いいえの評決ではありません。0をまたぐ広い区間は「まだ十分なデータがない」を意味します。
これはベイジアンですか? いいえ — これは頻度主義者のz検定で、最も広く教えられ使用されている方法です。ベイジアンA/Bツールはp値の代わりに「Bが Aを打ち負かす確率」を報告します;両方とも有効で、わずかに異なる質問に答えます。