論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説
📚 用語解説
A/Bテスト
A/B Testing
仮説検定

🔖 キーワード索引

#RCT#ランダム化#群間比較#p値#効果量#因果推論#コンバージョン率#サンプルサイズ#統計検定力#覗き見問題

ab test」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「ab test」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

ab test統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「ab test の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30秒で分かる結論

🍰 まずはやさしく

2つの案を比べる実験のことです。

どちらがより優れているか決めます。

アプリのボタンの色を比べる時に使います。

この章ではテストのやり方を学びます。

A/Bテスト:2 案 (A と B) を、 ランダムに分けたユーザー集団それぞれに見せ、 統計検定で「どちらが優れているか」を判定する実験手法

📍 文脈ボックス

🍰 まずはやさしく

仮説検定(正しいか確かめること)の一種です。

データの背景にある原因を探るために使います。

スマホの画面設計などでよく使われる手法です。

この章ではこの用語がどう使われるか読みます。

この用語は 仮説検定 カテゴリに属します。 関連する別称・略号:スプリットテスト、 ランダム化対照試験 (RCT) の Web 版

論文・実務レポートで A/Bテスト が登場したら、 まず本ページの「30秒で分かる結論」と「直感で掴む」を読めば、 その文脈で何を言っているか把握できます。 続いて数式・計算例・Python 実装に進むと、 自分の手元データで再現できる状態になります。

A/Bテストは、 単なる「平均値比較」ではなく、 因果推論の枠組み (Neyman-Rubin の潜在的結果モデル) に立脚しています。 ランダム化によって交絡変数がバランスし、 観察データでは得られない因果効果を推定できる ── これが Web 業界で広く使われる根本理由です。 SSDSE-B-2026 のような観察データでは A/B テストは直接できませんが、 「仮想的にランダム化したら何が起こるか」を考えるシミュレーション素材として有用です。

🎨 直感で掴む

🍰 まずはやさしく

どっちが良いかユーザーに決めてもらう方法です。

個人の好みではなく数字で判断するために使います。

買い物サイトのボタンの色を比べる例が近いです。

この章ではなぜランダムに分けるのかを読みます。

Web サイトのボタンの色を「青」と「赤」のどちらにすべきか悩んだとします。 「青の方が冷静で信頼感がある」「赤の方が目立つ」── 議論しても結論は出ません。 だったらユーザーに決めてもらいましょう。 訪問者の半分にはランダムに青を、 残り半分には赤を見せて、 クリック率を測定します。 ランダム割当ですから 2 群の年齢・性別・興味は確率的に等しくなり、 「青と赤」以外の差は平均してゼロ。 残ったクリック率の差は「色のせい」と 因果推論 できます ── これが A/B テスト

医学の ランダム化対照試験 (RCT) と本質は同じです。 患者を新薬・偽薬にランダム割当し、 治癒率を比較する。 「観察データ (誰がどの薬を選んだか) では選択バイアスが入る」── この欠点をランダム化で解消したのが RCT/A/B テストです。

ポイントは 「ランダム化」「事前に終了条件を決める」「効果量と CI を必ず併記」 の 3 点。 これを守らないと、 単なる p ハッキング (有意な結果を引き出す悪手) に堕します。

🎮 触って理解する

スライダーを動かして、 A 群 (対照) と B 群 (処置) のコンバージョン率、 および各群のサンプルサイズ n を変えてみましょう。 2 標本比率の差の検定 (プールした Z 統計量、 χ² は Z² に一致) の統計量・両側 p 値・効果量の 95% 信頼区間がリアルタイムで再計算され、 下の図に反映されます。 サンプルサイズを増やすと、 ほんの小さな差でも「有意」になっていく様子を体感してください。 図の上を左右にドラッグ/スワイプしても n を変えられます。

A 群 CV数 / n
50 / 1,000
B 群 CV数 / n
60 / 1,000
観測された差 Δ̂ = p̂_B − p̂_A
+1.00pt
プール比率 p̂
5.50%
Z 統計量
1.02
χ² (= Z², df=1)
1.04
両側 p 値
0.3082
差の 95% 信頼区間
[−0.93, +2.93]pt
必要 n (検出力80%, α=5%)
8,600 / 群
判定:有意ではない (p ≥ 0.05)

この図から読み取れること (直感)

⚠️ この体験に潜む落とし穴

覗き見問題 (Peeking)
n スライダーをじわじわ上げて「有意になった瞬間に止める」を繰り返すと、 真の差が 0 でもいつか偶然 $p<0.05$ を踏む。 実運用では偽陽性率が 5% → 30%超 に膨張する。 対策は事前に終了条件 (n・期間) を固定すること、 途中で見るなら有意水準を調整するか逐次検定を使うこと。
多重検定 (Multiple Testing)
この図は指標 1 つだが、 実務では複数指標・複数セグメントを同時に見る。 20 個検定すれば偶然 1 個有意になる確率は約 64% ($1-0.95^{20}$)。 多重検定補正 (Bonferroni / BH) と主指標の事前固定が必須。
統計的有意 ≠ 実質的有意
n を極端に大きくすると、 0.05pt のような実務上ほぼ無意味な差でも $p<0.05$ になる。 p 値は「差の有無」しか語らない。 「差の大きさが事業的に意味あるか」は効果量信頼区間絶対幅で判断する。 上の CI が [+0.01, +0.09]pt なら統計的には有意でも、 打つ手に値しないかもしれない。

🚀 発展:この先の世界

📐 定義・数式

🍰 まずはやさしく

比率の差を計算する数式のことです。

結果が偶然ではないことを証明するために使います。

部活の練習方法で成果が変わるかを調べるイメージです。

この章では計算式や必要な人数について読みます。

【2 標本比率の差の検定 (Wald の Z 統計量)】
$$ \hat{\Delta} = \hat{p}_B - \hat{p}_A, \quad Z = \frac{\hat{\Delta}}{\sqrt{\hat{p}(1-\hat{p})\left(\frac{1}{n_A} + \frac{1}{n_B}\right)}}, \quad \hat{p} = \frac{x_A + x_B}{n_A + n_B} $$

B 群の標本比率から A 群の標本比率を引いた値 $\hat{\Delta}$ が推定効果。 これを「両群を合わせた標本比率 $\hat{p}$ を用いた共通分散」の標準誤差で割った Z 統計量を標準正規分布で評価します。 $|Z| > 1.96$ なら $p < 0.05$ で有意。

【サンプルサイズ設計式】
$$ n \approx \frac{2 \cdot (z_{1-\alpha/2} + z_{1-\beta})^2 \cdot \bar{p}(1-\bar{p})}{\delta^2} $$

検出したい効果量 $\delta$ (2 群の比率差)、 有意水準 $\alpha$、 検出力 $1-\beta$ から必要 $n$ (各群のサンプルサイズ) を逆算します。 $\bar{p}$ は両群共通に想定するベースライン比率、 $z_{1-\alpha/2}, z_{1-\beta}$ は標準正規分布の分位点 (例:$\alpha=0.05$ で $z_{0.975}=1.96$、 検出力 80% で $z_{0.8}=0.84$)。 効果が小さいと、 必要 $n$ は急増します ($\delta$ の 2 乗の逆数)。

【効果量の信頼区間】
$$ \hat{\Delta} \pm 1.96 \cdot \sqrt{\frac{\hat{p}_A(1-\hat{p}_A)}{n_A} + \frac{\hat{p}_B(1-\hat{p}_B)}{n_B}} $$

95% CI が 0 をまたぐかどうかが、 5% 有意水準と等価。 p 値だけでなく CI を必ず報告するのが現代的作法です。

🔬 数式を言葉で読み解く

数式に出てくる記号の意味を 1 つずつ確認しましょう。 数式は記号の羅列に見えますが、 各記号は「ある量」「ある操作」「ある関係」を表す名札にすぎません。

A 群 (対照, Control)
現行版。 ベースライン。 比較の基準。 「もし何も変えなかったら」を体現する群。
B 群 (処置, Treatment)
新バージョン。 介入を加えた群。 「もし介入したら」を体現する群。
$x_A, x_B$
各群の成功件数 (例:クリック数、 購入件数)。
$n_A, n_B$
各群のサンプルサイズ。 通常 50:50 だが、 段階展開時は 10:90 などにすることも。
$\hat{p}_A, \hat{p}_B$
各群の標本比率 (例:クリック率)。 母比率 $p_A, p_B$ の推定量。
$\hat{\Delta}$
推定された処置効果 (リフト, lift)。 絶対値で報告するか、 相対値 $\hat{\Delta}/\hat{p}_A$ で報告するかは目的次第。
$Z$
標準化された検定統計量。 帰無仮説の下で標準正規分布に従う。
p 値
「効果が無い (帰無仮説) と仮定したとき、 今回以上に極端な差が偶然出る確率」。 通常 $< 0.05$ で有意。
$\alpha, \beta$
$\alpha$ は有意水準 (第一種の過誤の確率)、 $\beta$ は第二種過誤確率。 $1-\beta$ が検出力 (Power)。

数式全体を日本語で言い換える

数式 $Z = \hat{\Delta} / \text{SE}(\hat{\Delta})$ を日本語に直すと、 「観測された差 ÷ もし差がなかったとした場合の差のバラつき」となります。 分子の $\hat{\Delta} = \hat{p}_B - \hat{p}_A$ は、 「B 群のクリック率から A 群のクリック率を引いた、 観測された差」。 分母は「帰無仮説 (差なし) の下で、 サンプル変動だけによって生じうる差のバラつき (標準誤差)」。

分母の中身を見ると、 $\hat{p}(1-\hat{p}) \cdot (1/n_A + 1/n_B)$ の平方根。 これは 2 群を合わせた共通比率 $\hat{p}$ から計算されるプール分散です。 $\hat{p}(1-\hat{p})$ はベルヌーイ分布の分散で、 $\hat{p}=0.5$ で最大、 $\hat{p}=0$ や $1$ で 0。 つまり、 「クリック率が極端 (ほぼ全員クリック or ほぼ誰もクリックしない) なほど、 ばらつきが小さく検出力が高まる」ことを意味します。

$1/n_A + 1/n_B$ は「両群のサンプル数の調和平均の逆数」。 $n$ が大きいほど分母が小さくなり、 同じ $\hat{\Delta}$ でも $Z$ が大きくなって有意になりやすい ── つまり、 サンプルサイズを増やせば、 ごく小さな効果でも統計的有意になることが式から読み取れます。

この Z 統計量を標準正規分布の累積分布関数 $\Phi$ に入れると、 p 値が出ます:両側検定なら $p = 2(1 - \Phi(|Z|))$。 慣習的に $p < 0.05$ なら「帰無仮説 (差なし) を棄却する」、 つまり「観測された差は偶然では説明できない」と結論します。

ただし注意: p 値は「効果の大きさ」ではなく「証拠の強さ」しか示しません。 巨大サンプルでは些末な差も $p < 0.001$ になります。 必ず効果量 $\hat{\Delta}$ と 95% 信頼区間を併記し、 「統計的有意 = 実務的に意味がある」と短絡しないようにしてください。 これが現代の A/B テスト報告のゴールデンスタンダードです。

🧮 SSDSE-B-2026 で計算してみる

SSDSE-B-2026 (2023 年, 47 都道府県) を「仮想 A/B テスト」に見立てます。 47 都道府県を「総人口 (A1101) 100 万人以上の県 (A 群)」と「100 万人未満の県 (B 群)」に分け、 「着工新設住宅戸数 H1800 を人口で割った『1000 人あたり新設住宅戸数』が全国平均 (5.56 戸) を超えるかどうか」を成功 / 失敗の二値結果として、 群間で比率差が有意かを A/B テスト風に検定します。 観察データなのでランダム化されていない点に注意。

STEP 1 群分け (A1101 で 100 万人閾値)
SSDSE-B-2026 の 2023 年データ 47 件を A1101 で分割: A 群 $n_A=37$ (北海道, 宮城, 茨城 …), B 群 $n_B=10$ (鳥取, 島根, 高知, 佐賀, 福井, 徳島, 山梨, 和歌山, 秋田, 香川 など人口 100 万未満)。
STEP 2 成功率計算 (H1800 / A1101 × 1000 が全国平均超え)
全国平均 H1800/人口×1000 は 5.56 戸。 A 群成功数 $x_A=19$ / 37 で $\hat{p}_A = 19/37 = 0.5135$、 B 群成功数 $x_B=1$ / 10 で $\hat{p}_B = 1/10 = 0.1000$ (SSDSE-B-2026 実値で集計)。
STEP 3 効果量 (📐 数式と同じ符号規約: $\hat{\Delta} = \hat{p}_B - \hat{p}_A$)
数式定義 ($\hat{\Delta} = \hat{p}_B - \hat{p}_A$, B が処置群) に従い、 ここでは B 群 = 小県 (100 万人未満, $n_B=10$)A 群 = 大県 (100 万人以上, $n_A=37$) と置く。 $\hat{\Delta} = \hat{p}_B - \hat{p}_A = 0.1000 - 0.5135 = -0.4135$ (B 群の成功率は A 群より 41.4 ポイント低い)。 Z 統計量は分子の符号で B 優位 / A 優位を表すので、 ここでは $\hat{\Delta} < 0$ より「A 群 (大県) が高成功率」と読み取れる。
STEP 4 検定統計量
プール比率 $\hat{p} = (x_A + x_B)/(n_A + n_B) = (19+1)/(37+10) = 20/47 = 0.4255$、 $\text{SE} = \sqrt{\hat{p}(1-\hat{p})(1/n_A + 1/n_B)} = \sqrt{0.4255 \cdot 0.5745 \cdot (1/37 + 1/10)} = \sqrt{0.031052} = 0.1762$、 $z = \hat{\Delta} / \text{SE} = -0.4135 / 0.1762 = -2.3466$ (両側検定では $|z|$ で判定するので絶対値 2.3466)。
STEP 5 p 値と結論
両側検定で $p = 2(1 - \Phi(|z|)) = 2(1 - \Phi(2.3466)) = 0.0189$。 $p < 0.05$ なので「A 群 (大県) と B 群 (小県) の 1000 人あたり新設住宅戸数の全国平均超え確率には統計的に有意な差がある」と判定。 $\hat{\Delta} < 0$ の符号から、 大県 (A) の成功率が小県 (B) より有意に高いと読み取る。 ただし観察データなので因果は言えず、 人口規模と相関する別要因 (経済規模、 雇用機会、 高齢化率など) が真の原因の可能性が高い。

SSDSE-B-2026 を「A/B テスト風に解析」した実例: A1101 (総人口) で群分け → H1800 (新設住宅戸数) を 1000 人あたりに正規化 → 全国平均超えを成功と定義 → 比率差検定 → $|z|=2.35$, $p=0.019$ で有意差あり。 重要なのは、 「観察データの群間差を A/B テスト風に検定しても、 因果は主張できない」という点。 因果を言うには、 ランダム化された介入実験 (例: 県知事を抽選し新規建築許可枠を割り当てる) が必要。

🧮 数式に値を入れて手で計算する

上の「群分け→成功率→z→p 値」の数値を、 SSDSE-B-2026 (2023 年・47 都道府県) の A 群 $n_A=37$ / $x_A=19$、 B 群 $n_B=10$ / $x_B=1$ をそのまま比率の差検定の数式に代入し、 Step 1〜5 で手計算を展開する。 合成データは使わず、 上のセクションと同一の実値で連動させる。 同じ計算を Python で再現し、 結果が完全一致することを確認する。

📐 比率の差検定 (再掲)

$$ z = \frac{\hat{p}_1 - \hat{p}_2}{\sqrt{\hat{p}(1-\hat{p})\left(\frac{1}{n_1} + \frac{1}{n_2}\right)}}, \quad \hat{p} = \frac{x_1 + x_2}{n_1 + n_2} $$

Step 1: データ準備 (SSDSE-B-2026, 2023 年 47 県を A1101 で群分け)

$n$成功数 $x$ (H1800/A1101×1000 が全国平均 5.56 超え)標本比率 $\hat{p}$
A (人口 100 万以上, 37 県)3719$19/37 \approx 0.5135$
B (人口 100 万未満, 10 県)101$1/10 = 0.1000$

Step 2: プール比率 $\hat{p}$

項目計算結果
$x_1 + x_2$$19 + 1$20
$n_1 + n_2$$37 + 10$47
$\hat{p}$$20 / 47$0.425532

Step 3: 標準誤差 SE

項目計算結果
$\hat{p}(1-\hat{p})$$0.425532 \times 0.574468$0.244454
$1/n_1 + 1/n_2$$1/37 + 1/10 = 0.027027 + 0.100000$0.127027
分散 (内側)$0.244454 \times 0.127027$0.031052
SE$\sqrt{0.031052}$0.176217

Step 4: 検定統計量 $z$

項目計算結果
$\hat{p}_1 - \hat{p}_2$ (A − B)$0.513514 - 0.100000$$+0.413514$
$z$$0.413514 / 0.176217$$+2.346619$

Step 5: 両側 p 値と結論

項目結果
$\lvert z \rvert$2.346619
両側 p 値 ($2 \times (1 - \Phi(\lvert z \rvert))$)0.018945
有意水準 $\alpha=0.05$ で判定$p < 0.05$ → 有意差あり (A 群 = 大県が高成功率)

🐍 同じ計算を Python で再現

🎯 このコードでやること: SSDSE-B-2026 を読み込んで A1101 (総人口) で 100 万人閾値に群分けし、 H1800/A1101×1000 が全国平均 5.56 を超える県の比率を A / B 群で集計、 比率の差検定で z と両側 p 値を出す (上の Step 1〜5 と完全に同じ値)。

📥 入力データ (SSDSE-B-2026, 2023 年, 47 県): 列 A1101 (総人口) と H1800 (新設住宅戸数) を使う。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import math
import pandas as pd
from scipy import stats

# Step 1: SSDSE-B-2026 を読み込み、2023 年 47 県を A1101 で群分け
df = pd.read_csv("data/raw/SSDSE-B-2026.csv", encoding="cp932", skiprows=[1])
df = df[df["SSDSE-B-2026"] == 2023].copy()  # 先頭列(年度)の実列名は "SSDSE-B-2026"
df["rate"] = df["H1800"] / df["A1101"] * 1000  # 1000 人あたり新設住宅戸数
nationwide_mean = 5.56  # 全国平均 (記事本文と一致)
df["success"] = (df["rate"] > nationwide_mean).astype(int)
A = df[df["A1101"] >= 1_000_000]
B = df[df["A1101"] <  1_000_000]
n1, n2 = len(A), len(B)            # 37, 10
x1, x2 = int(A["success"].sum()), int(B["success"].sum())  # 19, 1
p1, p2 = x1 / n1, x2 / n2

# Step 2: プール比率
p_pool = (x1 + x2) / (n1 + n2)

# Step 3: 標準誤差
se = math.sqrt(p_pool * (1 - p_pool) * (1/n1 + 1/n2))

# Step 4: z 値 (A − B、 数式の符号規約)
z = (p1 - p2) / se

# Step 5: 両側 p 値
pval = 2 * (1 - stats.norm.cdf(abs(z)))

print(f"n_A={n1}, x_A={x1}, p_A={p1:.6f}")
print(f"n_B={n2}, x_B={x2}, p_B={p2:.6f}")
print(f"p_pool={p_pool:.6f}, SE={se:.6f}, z={z:.6f}, two-sided p={pval:.6f}")

📤 実行結果

n_A=37, x_A=19, p_A=0.513514 n_B=10, x_B=1, p_B=0.100000 p_pool=0.425532, SE=0.176217, z=2.346619, two-sided p=0.018945

💬 手計算 (Step 2〜5) と Python 出力が完全一致 (p_pool=0.425532, SE=0.176217, $|z|$=2.346619, p=0.018945)。 上の章 7 前半 ($|z|\approx 2.35$, $p\approx 0.019$) とも値が一致。 $p < 0.05$ より「人口 100 万以上の県と未満の県の『1000 人あたり新設住宅戸数が全国平均超え』比率には有意差あり」と判定。 ただし観察データなので因果は主張できない (人口規模に相関する経済要因が真因の可能性)。

🐍 Python 実装

SSDSE-B-2026 のような実データに対して、 まずはコピペで動かしてみるのが理解の早道です。 各コードブロックには 🎯 目的 / 📥 入力 / 📤 出力 / 💬 ヒント の 4 要素ナレーションを付け、 「何のために書いた行か」を見失わないようにしています。

① 最小の A/B テスト:proportions_ztest

statsmodels の関数で 2 標本比率検定を行います。 SSDSE データに依存しない最小例。

🎯 目的:A/B 2 群の比率差を検定し、 Z 値と p 値を出す
📥 入力:各群の成功件数と試行数 (リスト)
📤 出力:Z 統計量 (正で B 優位)、 両側 p 値
💬 ヒント:usevar='pooled' (デフォルト) は共通比率仮定。 別分散は'unpooled'。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from statsmodels.stats.proportion import proportions_ztest
import numpy as np

# A 群: 10000 人中 200 クリック / B 群: 10000 人中 250 クリック
successes = np.array([200, 250])
trials    = np.array([10000, 10000])

z, p = proportions_ztest(successes, trials)
print(f'Z統計量 = {z:.3f}')
print(f'p値    = {p:.4f}')

# 効果量と95%信頼区間
p_A, p_B = successes / trials
delta = p_B - p_A
se = (p_A*(1-p_A)/trials[0] + p_B*(1-p_B)/trials[1])**0.5
ci_lo, ci_hi = delta - 1.96*se, delta + 1.96*se
print(f'効果量 Δ = {delta:.4f}  95%CI=[{ci_lo:.4f}, {ci_hi:.4f}]')

出力例:Z統計量 ≈ -2.38, p値 ≈ 0.0171。 B 群のクリック率が A より統計的有意に高い (p < 0.05) ことが分かります。 符号は引数の順序に依存する点に注意 (ここでは第 1 引数が A 群なので、 Z が負 = B 群優位)。

② SSDSE-B-2026 を読み込み、 群分け A/B 風検定

実際の都道府県データを 2 群に分け、 ある指標の群間差を検定します。

🎯 目的:SSDSE-B-2026 の特定列で 2 群比較を実施
📥 入力:data/raw/SSDSE-B-2026.csv (公的データ)
📤 出力:群間平均差、 t 値、 p 値、 95% CI
💬 ヒント:カラム名は 1 行目で確認。 数値の単位 (人/千人/%) も要チェック。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import pandas as pd
from scipy import stats

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].copy()  # 先頭列(年度)で2023年 47県に絞る

# A1101 = 総人口、 B4101 = 平均気温(いずれも SSDSE-B-2026 実在列)
median_pop = df['A1101'].median()
A = df[df['A1101'] >= median_pop]  # 人口大の県
B = df[df['A1101'] <  median_pop]  # 人口小の県

target = 'B4101'  # SSDSE実在の指標列名に置換可
tstat, pval = stats.ttest_ind(A[target], B[target], equal_var=False)
print(f'A群 平均 = {A[target].mean():.2f}, nA = {len(A)}')
print(f'B群 平均 = {B[target].mean():.2f}, nB = {len(B)}')
print(f't = {tstat:.3f}, p = {pval:.4f}')

Welch の t 検定 (equal_var=False) を採用。 等分散仮定が成立しない実データでロバストに動きます。 観察データなので、 有意差が出ても「人口規模と相関する別要因」が原因の可能性が高い点に留意。

③ サンプルサイズ設計 (Power Analysis)

A/B テストを始める前に、 「効果量 1%、 検出力 80%、 有意水準 5%」で必要な n を逆算します。

🎯 目的:事前にサンプルサイズを設計し、 無駄なテストを避ける
📥 入力:想定効果量、 ベースライン比率、 α、 β
📤 出力:各群の必要サンプル数
💬 ヒント:effect_size は Cohen の h (比率の効果量)。 通常 0.02-0.05 程度。
1
2
3
4
5
6
7
8
9
10
11
from statsmodels.stats.power import NormalIndPower
from statsmodels.stats.proportion import proportion_effectsize

p1 = 0.02   # 現行クリック率 2%
p2 = 0.025  # 期待クリック率 2.5% (絶対0.5pt改善)
h = proportion_effectsize(p2, p1)  # Cohen's h

analysis = NormalIndPower()
n = analysis.solve_power(effect_size=h, alpha=0.05, power=0.8, alternative='two-sided')
print(f'各群必要 n = {int(n):,}人')
print(f'両群合計  = {int(n)*2:,}人')

実行例:各群 約13,800人、 合計 約27,500人。 小さい効果を確実に検出するには、 膨大なトラフィックが必要だと分かります。 これが「A/B テストは大企業の独擅場」と言われる所以。

④ 多腕バンディット (Multi-Armed Bandit) で適応的に切替

固定 A/B ではなく、 効果が高い腕に動的にトラフィックを振る Thompson Sampling の例。

🎯 目的:リアルタイムに最良案へ流入を寄せ、 機会損失を最小化
📥 入力:各腕の累積成功・失敗数
📤 出力:各イテレーションでの選択腕、 最終的な勝者
💬 ヒント:ベータ分布からのサンプリングで自然に exploration/exploitation バランス。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

true_ctr = [0.020, 0.025]  # 2腕の真のクリック率
alpha = np.ones(2); beta = np.ones(2)
n_iter = 20000

for t in range(n_iter):
    # Thompson Sampling: 事後ベータ分布からサンプル
    theta = [np.random.beta(alpha[k], beta[k]) for k in range(2)]
    arm = int(np.argmax(theta))
    reward = np.random.binomial(1, true_ctr[arm])
    alpha[arm] += reward
    beta[arm]  += (1 - reward)

for k in range(2):
    mean = alpha[k] / (alpha[k]+beta[k])
    print(f'腕{k}: 推定CTR={mean:.4f}, 試行={int(alpha[k]+beta[k]-2):,}')

結果:勝者の腕により多く流入が寄せられるため、 機会損失 (regret) が固定 A/B より小さくなります。 ただし因果効果の点推定としては A/B 固定の方が分散が小さい。 目的次第で使い分け。

⑤ CUPED:事前データで分散削減

事前期間 (Pre-period) の同指標を共変量として使い、 結果指標の分散を減らす Microsoft 発の手法。

🎯 目的:同じサンプル数でも検出力を 2 倍に近づける
📥 入力:実験期間の Y, 事前期間の X
📤 出力:調整後の Y* と検定結果
💬 ヒント:X と Y の相関が高いほど分散削減効果大。 0.7 で約 50% 削減。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import numpy as np
from scipy import stats

# シミュレーション: 事前期間と本実験で相関のあるユーザーレベル指標
rng = np.random.default_rng(42)
n = 5000
X = rng.normal(100, 20, n)              # 事前期間の指標
treat = rng.binomial(1, 0.5, n)
Y = X*0.8 + treat*2 + rng.normal(0, 10, n)  # 本実験指標

# CUPED 変換: Y* = Y - theta*(X - mean(X))
theta = np.cov(Y, X, bias=True)[0,1] / np.var(X)
Y_adj = Y - theta * (X - X.mean())

# Raw vs CUPED の t 検定
t_raw, p_raw = stats.ttest_ind(Y[treat==1], Y[treat==0])
t_cup, p_cup = stats.ttest_ind(Y_adj[treat==1], Y_adj[treat==0])
print(f'Raw   t={t_raw:.2f}, p={p_raw:.5f}')
print(f'CUPED t={t_cup:.2f}, p={p_cup:.5f}')
📤 実行例(実測) Raw t=4.58, p=0.00000 CUPED t=7.18, p=0.00000

CUPED 後の t 値は Raw より大きくなり、 p 値が小さくなることが多い (同じ真の効果で検出力↑)。 X と Y が無相関なら効果なし。 Microsoft Bing で標準採用、 Booking.com 等も導入。

⚠️ よくある落とし穴

A/B テストで陥りがちな失敗パターン。 「Peeking(途中で何度も検定して有意になった瞬間に止める)」「サンプルサイズ計算をせず勘で止める」「SUTVA 違反(ユーザー間で介入が干渉する)」「複数指標を同時検定して補正を忘れる」「Novelty Effect の無視」など、 Web 計測・グロース現場ではほぼ全員が一度はハマる落とし穴です。

❌ 覗き見問題 (Peeking)
途中で何度も p 値を見て「有意になったら止める」をやると、 偽陽性率が 5% から 30%+ に跳ね上がる。 事前に終了条件 (期間/n) を決め、 中間解析するなら α を Pocock や O'Brien-Fleming で調整。
❌ サンプルサイズ不足
効果が小さい (1% のリフトなど) 場合、 数万〜数十万人必要。 検出力不足の A/B は「差が分からない」だけで、 「差が無い」とは言えない。 事前に Power Analysis を実施せよ。
❌ ノベルティ効果と慣れ
新版は最初だけ目新しさで反応が良い (ノベルティ)、 逆に既存ユーザーは新 UI に戸惑い指標が下がる (プライマシー)。 最低 1-2 週間の安定期間を見るのが鉄則。
❌ SUTVA 違反 (相互作用)
SNS や 2 サイドマーケットでは、 ユーザー間で介入効果が漏れる (Spillover)。 単純 A/B では因果は推定できない。 クラスタ単位 A/B やスイッチバック実験を検討。
❌ 多重検定の見落とし
指標を 20 個追って 1 個が有意なら、 偶然有意の確率は約 64% ($1-0.95^{20}$)。 Bonferroni 補正や FDR 制御 (BH 法) で α を割る。 主指標 (Primary KPI) を 1 つに絞る運用も有効。 詳細は多重検定を参照。
❌ 相対値の罠
「25% 改善!」が絶対値では 0.5pt にすぎないことも。 ベースラインが小さいと相対変化は大袈裟になる。 絶対値・相対値・絶対 CI を必ず併記。
❌ 介入の整合性検証 (SRM)
A:B = 50:50 のはずが、 実は 51:49 にズレていたら、 ランダム化が壊れているサイン (Sample Ratio Mismatch)。 χ² 検定で必ず事前チェック。

📝 補足:本文が触れていない3つの落とし穴 — シンプソンのパラドックス・外部妥当性・生存者バイアス

上の「⚠️ よくある落とし穴」(覗き見・SRM・SUTVA・多重検定・ノベルティ …) は検定を回す段階の罠だった。 ここでは角度を変え、 群を合算・分割する段階結果を別の場面へ外挿する段階で起きる、 見落としやすい罠を3つ補う。

① シンプソンのパラドックス(層別すると符号が逆転する)
全体では B が勝っていても、 セグメント(新規/既存・OS・国)ごとに見ると全セグメントで A が勝つ、 という逆転が起こりうる。 原因は交絡群サイズの偏りだ。 (架空の数値例) 処置群 CVR 5.0%・対照群 4.5% で「B の勝ち」に見えても、 処置群にたまたま反応の良いモバイル層が多く割り当たっていると、 モバイル層でも PC 層でも対照が勝っている、 ということが起こる ── これがパラドックスの正体。 ランダム化が正しく効いていれば原理的に起きないが、 割当のバグや事後の絞り込み(後述の生存者バイアス)で容易に混入する。 対策:主要セグメントの効果も併記し、 χ² で割当バランス(SRM)を確認する。 実測での層別の挙動は次の「📝 補足:連続指標の平均差検定」で SSDSE-B-2026 を使って確かめる。
② 外部妥当性(内部で正しくても、外へ一般化できるとは限らない)
ランダム化は内部妥当性(この実験内で因果が正しい)を保証するが、 外部妥当性(別の期間・市場・母集団へ一般化できるか)は別問題。 2週間の勝ちが、 季節性・同時期のキャンペーン・母集団構成の変化で年間を通じては再現しない、 は日常茶飯事だ。 一部トラフィックでの勝ちが 100% 展開後も持続する保証もない(希釈・混雑効果)。 対策:重要な意思決定は期間・セグメントを変えた再現テスト(リプリケーション)で裏を取り、 「いつ・誰に・どの文脈で」効いたのかを明記する。
③ 生存者バイアス(割当後に対象を絞ると効果が歪む)
分析対象を「最後まで残った(生き残った)ユーザー」に絞ると、 処置が離脱を促した悪影響が見えなくなる。 例:新 UI に不満なユーザーが離脱し、 残った人だけで満足度を測ると「B のほうが満足度が高い」と誤読する。 これは選択バイアスの一種で、 「割当後の変数でフィルタする」と必ず生じる。 対策:ITT(Intention-To-Treat)原則で「割り当てた全員」を分母に据える。 アクティブユーザー限定・購入者限定などの事後フィルタは、 それ自体が処置の結果でありうるため厳禁。

📝 補足:連続指標の平均差検定と分散削減 — 必要 n・層別・CUPED・異質処置効果

本文の「🧮 SSDSE-B-2026 で計算してみる」は、 指標を「全国平均を超えたか」の二値に潰して比率差検定した。 だが二値化は情報を捨て、 検出力を下げる。 ここでは同じ SSDSE-B-2026(2023 年・47 都道府県、 encoding='cp932'skiprows=[1])の 1000 人あたり新設住宅戸数(H1800 / A1101 × 1000)を連続量のまま、 2 群の平均差検定にかける(すべて実測値)。 群分けは本文と同じ A1101(総人口 100 万人)閾値。

連続指標の 2 標本平均差検定(Welch)

$n$平均(戸)標準偏差
A(人口 100 万以上, 大県)375.7731.170
B(人口 100 万未満, 小県)104.7940.905

平均差 $\bar{x}_A - \bar{x}_B = +0.979$ 戸。 Welch の t 検定で $t = 2.84,\ p = 0.011$、 分散を等しいと仮定したプール t でも $t = 2.45,\ p = 0.018$(本文の比率差検定 $|z|=2.35,\ p=0.019$ と符号・結論が一致)。 二値化せず連続量を使うと p 値が 0.019 → 0.011 に下がり検出力が上がるのが読み取れる(情報を捨てないため)。 効果量 Cohen's $d = (\bar{x}_A-\bar{x}_B)/s_{\text{pooled}} = 0.979/1.122 = 0.87$(大きな効果)。

必要サンプルサイズ(この効果量を検出力 80% で捉えるには)

連続量の平均差検定の必要 $n$(1 群あたり、 両側 $\alpha=0.05$・検出力 $1-\beta=0.80$)は $ n \approx 2\,(z_{1-\alpha/2}+z_{1-\beta})^2 / d^2 = 2\,(1.96+0.84)^2 / 0.87^2 \approx \mathbf{21}$ 人/群。 効果量が $d=0.87$ と大きいので、 わずか 21 県ぶんで足りる計算(実測は 37 対 10 なので十分検出できていた)。 🎮 ウィジェットの「必要 n = 8,600/群」は比率差 1pt という微小効果を狙う設定だったのに対し、 ここは大きな効果なので必要 n が桁違いに小さい ── 必要 n は効果量の 2 乗に反比例することの実測的な裏付けになる。 詳細は検出力分析サンプルサイズ効果量を参照。

層別による交絡の可視化(シンプソンの実測チェック)

補足1のシンプソンのパラドックスを実測で確かめる。 高齢化率(A1303 / A1101、 中央値 0.318)で 2 層に分け、 各層で大県 vs 小県を比較した(実測値):

層(高齢化率)大県(平均戸/$n$)小県(平均戸/$n$)大県−小県
若い層(< 0.318)6.22 / 215.98 / 2+0.24
高齢層(≥ 0.318)5.18 / 164.50 / 8+0.69

今回は符号は逆転しなかった(両層とも大県が上)が、 小県 10 県のうち 8 県が高齢層に偏っていることが分かる。 つまり「小県ほど高齢」で、 高齢の県は新設住宅戸数が少ない ── 交絡が明瞭に効いており、 全体差 +0.98 のうち一部は「小県が高齢な県に偏る」せいだ。 層別(stratification)で交絡を調整すると効果はより正確に読める。 割当がランダムなら層別は不要だが、 観察データ(今回)や割当が偏った実験では必須の作法。

CUPED(分散削減で検出力を底上げ)
CUPED(Controlled-experiment Using Pre-Experiment Data)は、 実験前の同じ指標を共変量にして結果を回帰調整し、 個人差由来のノイズを差し引く手法。 層別の連続版といえる。 交絡を消すのではなく(ランダム化済みが前提)、 分散を 20〜50% 削って同じ n でも検出力を上げる/必要 n を減らす。 上の「連続量にすると p が下がる」を、 事前データでさらに推し進めたものと理解するとよい。
異質処置効果(HTE)— 平均効果だけ見ない
上の層別で大県優位が「若い層 +0.24/高齢層 +0.69」と層で大きさが違うこと自体が、 効果が一様でない(異質処置効果, Heterogeneous Treatment Effect)ことの兆候だ。 平均処置効果(ATE)だけ見ると「誰に効くか」を見落とす。 ただしサブグループを後から多数切ると多重比較で偽陽性が出やすいので、 分析するセグメントは事前登録が鉄則。 近年は因果木・メタ学習器で HTE を推定する手法が発展している。

🗺 概念マップでの位置づけ

A/Bテスト は 仮説検定 カテゴリの中で、 上位概念・並列概念・下位概念のネットワークに位置します。 関係を簡略図で示します。

┌─────────────────────────────────────────┐ │ 統計的推論 (Statistical Inference) │ └────────┬────────────────────┬──────────────┘ │ │ ┌─────▼──────┐ ┌──▼─────────┐ │ 仮説検定 │ │ 推定 (CI) │ │ Hypothesis │ │ Estimation │ └─────┬──────┘ └────────────┘ │ ┌─────▼──────────────┐ │ ★ A/Bテスト ★ │ ← 現在地 │ (2 群ランダム化比較) │ └─┬─────┬─────┬───┬──┘ │ │ │ │ ┌──▼─┐┌──▼──┐┌─▼─┐┌▼──────────┐ │RCT ││多腕 ││CUPED││スイッチ │ │医療││バンディ ││分散 ││バック実験 │ │ ││ット ││削減 ││ │ └────┘└──────┘└─────┘└───────────┘ │ ▼ 因果推論 (Causal Inference)

より詳細な関係は 🗺 概念マップ で全体像を確認できます。

🧭 サイト内ナビゲーション

本ページは、 統計・データ解析コンペティションの再現論文集に付随する用語解説の 1 ページです。 A/Bテスト 以外の用語も、 同じフォーマットで以下からたどれます。

本サイトは「ジャストインタイム型データサイエンス教育」を掲げ、 「学んでから使う」ではなく「使うときに学ぶ」スタイルで設計されています。

A/Bテスト 統計的推論 多腕バンディット CUPED 分散削減 因果推論 仮説検定 ランダム化比較試験

🔗 隣接手法への橋渡し

章 10 (🌐 関連手法・派生) は隣接技術の「鳥瞰」だったが、 ここでは 実務で A/B テストと隣接手法をどう繋ぐか・どう統合するか・いつ切替えるかを 3 視点で整理する。 章 15 (🌳 手法選択フロー) が「最初に何を選ぶか」を答えるなら、 章 14 は「選んだ後に隣接手法とどう連携するか」を答える。

① 接続 (Connection) — 前後工程との繋ぎ方

② 統合 (Integration) — 同時利用・組合せ

③ 比較 (Comparison) — 切替判断の早見表

手法A/B からの切替条件代替で得られる利点注意点
多腕バンディット機会損失最小化が優先 / 短期 KPI 重視勝者腕に動的に流量集約、 累積報酬 +15-30%統計的に厳密な「効果量推定」は出ない
因果推論 (PSM/DID)ランダム化不可 (倫理 / 業界規制)過去ログから ATE 推定、 実験不要交絡未測定の仮定が崩れると無効
Switchback ExperimentSUTVA 違反 (配車・配達・SNS)同一ユーザーが両条件経験で交絡除去時間相関の補正が必要
逐次検定 (Sequential)途中覗き見が避けられない経営要件always-valid p で覗き見問題解消必要 N が固定 A/B より 30% 程度増
ベイジアン A/B「勝つ確率」で意思決定したい事前情報を組込め、 解釈が直感的事前分布の選択が結論を左右

この 3 視点を押さえると、 章 15 のフローで「A/B」を選んだ後も、 隣接手法と組み合わせて段階的に高度化できる。 「A/B 一本足打法」から「A/B + 多腕バンディット + 因果推論」の統合運用に移行することで、 SSDSE-B 47 都道府県のように多様な対象群でも頑健な意思決定が可能になる。

🌳 手法選択フロー

「A/Bテスト」を実施するか、 観察データの因果推論や多腕バンディットに切り替えるかを、 ランダム化可否・SUTVA 成立・必要 N の 3 軸で判定する。 単純な検定一本ではなく、 設計段階で代替も検討すべきである。

  1. 分岐 1 (前提条件: ランダム化): 「ランダム化割当が可能か?」 Yes → 次の分岐へ進む、 No → 観察データの因果推論体系 (傾向スコア操作変数) に切り替え。 上流の仮説検定枠組みは観察データでは「相関」しか保証しない。
  2. 分岐 2 (戦略選択: 静的 vs 動的): 「学習しながら最適化したいか?」 No (固定比率で完了まで実験) → 通常の A/B テスト、 Yes (期間中も性能良い腕に流量を寄せたい) → 多腕バンディット (Thompson Sampling / UCB)。 ch14 で並列代替として挙げた手法はここで選ばれる。
  3. 分岐 3 (手法特性: 相互作用): 「SUTVA (群間相互作用なし) が成立するか?」 Yes → ユーザー単位ランダム化で OK、 No (ネットワーク効果あり) → クラスタ単位 / Switchback Experiment へ移行。
  4. 分岐 4 (運用要件: 必要 N): 「効果量と検出力から必要 N が現実的か?」 Yes → 走らせる、 No → 効果量を見直すか、 CUPED 等で分散削減して N を圧縮。 N 不足のまま p 値だけ見ると 第二種過誤を量産する。

この 4 分岐は ch14 で挙げた 3 つの隣接概念 (上流=仮説検定、 並列=多腕バンディット、 下流=因果推論) と 1 対 1 で対応する: 分岐 1=下流の因果、 分岐 2=並列の動的選択、 分岐 4=上流の検定設計。 フローは出発点であって絶対解ではない。 領域知識・データ特性・運用制約を加えて最終判断する。 迷ったときは「🔗 隣接手法への橋渡し」と「🌐 関連手法・派生」を見直し、 単一の手法に固執しないこと。