【Streamlit】A/Bテストの結果分析アプリ:統計的評価の可視化

Streamlit
この記事は約15分で読めます。

こんにちは、JS2IIUです。
今回はA/BテストのアプリをStreamlit上に構築していきたいと思います。統計的な処理を入れたアプリにしていきます。今回もよろしくお願いします。

はじめに

Webサイトやアプリの改善において、「どちらのデザインがより効果的か?」を検証する方法としてA/Bテストは非常に有効です。

本記事では、PythonのStreamlitというツールを使って、A/Bテストの結果データを読み込み、統計的に効果を評価し、グラフで可視化するアプリを作る方法を解説します。

A/Bテストとは?

そもそもA/Bテストとは?

A/Bテストとは、2つのパターン(AとB)を比較し、どちらがより効果的かをデータで判断する方法です。

たとえば、

  • A:青いボタン
  • B:赤いボタン

この2つを同じ条件で表示し、どちらのクリック率が高いかを比較することで、「赤いボタンの方が効果的だ」といった判断ができます。

A/Bテストでよく使われる指標

  • コンバージョン率(CVR):クリック・購入・登録など
  • クリック率(CTR)
  • 滞在時間離脱率

統計的に効果を評価するとは?

「Bの方がCVRが高かった!」だけでは本当に効果があるとは言えません。たまたま差が出ただけかもしれないからです。

そこで使うのが統計的検定です。

ポイント用語(ざっくりと・・・)

用語意味
p値(p-value)「偶然でこの差が出る確率」。値が小さいほど偶然とは言いにくい。
有意水準(例:0.05)p値がこの値より小さければ「統計的に有意」と判断します。

たとえば、

  • p値 = 0.03 → 偶然ではない(有意差あり)
  • p値 = 0.12 → 偶然の可能性がある(有意差なし)

アプリを作る手順

ステップ1:必要なライブラリのインストール

まずは以下のライブラリをインストールしてください。

Bash
pip install streamlit pandas scipy

ステップ2:サンプルデータの準備

まず、次のようなCSVファイルを用意しましょう(ab_test_data.csvなどの名前で保存):

Plaintext
group,conversion
A,1
A,0
A,1
B,0
B,1
B,1
  • group: A or B を示します
  • conversion: 成果があったか(1)なかったか(0)

ステップ3:Streamlitアプリの作成

以下のコードを ab_test_app.py という名前で保存してください。

Python
import streamlit as st
import pandas as pd
from scipy.stats import chi2_contingency
import matplotlib.pyplot as plt

st.title("🔍 A/Bテスト結果分析アプリ")

# ファイルアップロード
uploaded_file = st.file_uploader("A/Bテスト結果のCSVファイルをアップロードしてください", type="csv")

if uploaded_file is not None:
    # データ読み込み
    df = pd.read_csv(uploaded_file)
    st.subheader("📄 アップロードされたデータ")
    st.dataframe(df)

    # 集計
    summary = df.groupby('group')['conversion'].agg(['sum', 'count'])
    summary['conversion_rate'] = summary['sum'] / summary['count']

    st.subheader("📊 コンバージョン率の比較")
    st.dataframe(summary)

    # 可視化
    fig, ax = plt.subplots()
    summary['conversion_rate'].plot(kind='bar', color=['skyblue', 'salmon'], ax=ax)
    ax.set_ylabel("Conversion Rate")
    st.pyplot(fig)

    # カイ二乗検定
    contingency_table = pd.crosstab(df['group'], df['conversion'])
    chi2, p, dof, expected = chi2_contingency(contingency_table)

    st.subheader("📈 統計的検定の結果(カイ二乗検定)")
    st.write(f"**p値(p-value)**: `{p:.4f}`")

    if p < 0.05:
        st.success("この結果には統計的に有意な差があります(p < 0.05)")
    else:
        st.info("統計的に有意な差は見られません(p ≥ 0.05)")
else:
    st.info("CSVファイルをアップロードしてください")

1. 必要なライブラリをインポート

Python
import streamlit as st
import pandas as pd
from scipy.stats import chi2_contingency
import matplotlib.pyplot as plt
  • streamlit (st): Streamlitライブラリを使って、インタラクティブなウェブアプリケーションを作成します。
  • pandas (pd): データフレームの操作や集計に使用します。
  • scipy.statschi2_contingency: カイ二乗検定を実行するために使用します。これは、A/Bテストの結果が統計的に有意かどうかを評価するための手法です。
  • matplotlib.pyplot (plt): グラフを描画するためのライブラリです。コンバージョン率をバーグラフで可視化します。

2. アプリケーションのタイトルを設定

Python
st.title("🔍 A/Bテスト結果分析アプリ")
  • st.title(): アプリケーションのタイトルを設定します。この場合、「🔍 A/Bテスト結果分析アプリ」というタイトルが画面に表示されます。

3. ユーザーによるCSVファイルのアップロード

Python
uploaded_file = st.file_uploader("A/Bテスト結果のCSVファイルをアップロードしてください", type="csv")
  • st.file_uploader(): ユーザーがCSVファイルをアップロードできるウィジェットを表示します。type="csv"で、アップロードするファイルがCSV形式であることを指定しています。
  • 変数uploaded_fileにアップロードされたファイルが保存されます。

4. アップロードされたファイルの処理

Python
if uploaded_file is not None:
    # データ読み込み
    df = pd.read_csv(uploaded_file)
    st.subheader("📄 アップロードされたデータ")
    st.dataframe(df)
  • if uploaded_file is not None: ユーザーがファイルをアップロードした場合、処理が実行されます。
  • pd.read_csv(uploaded_file): アップロードされたCSVファイルをpandasのデータフレーム(df)として読み込みます。
  • st.subheader(): セクションの小見出しを表示します。ここでは「📄 アップロードされたデータ」という小見出しを表示します。
  • st.dataframe(): アップロードされたデータを表形式で表示します。これにより、データフレームがStreamlitアプリに表示されます。

5. A/Bテスト結果の集計

Python
    # 集計
    summary = df.groupby('group')['conversion'].agg(['sum', 'count'])
    summary['conversion_rate'] = summary['sum'] / summary['count']

    st.subheader("📊 コンバージョン率の比較")
    st.dataframe(summary)
  • df.groupby(‘group’)[‘conversion’].agg([‘sum’, ‘count’]): group(A/Bグループ)ごとにconversion(コンバージョン結果)の合計(sum)と件数(count)を集計します。
  • 例えば、Aグループで何人がコンバージョンしたか、何人が全体で試行したかを計算します。
  • summary[‘conversion_rate’] = summary[‘sum’] / summary[‘count’]: コンバージョン率を計算します。コンバージョン率は「コンバージョンした人数 / 全体人数」で求められます。
  • st.subheader(“📊 コンバージョン率の比較”): セクションの小見出し「📊 コンバージョン率の比較」を表示します。
  • st.dataframe(summary): 集計結果を表形式で表示します。

6. 可視化(バーグラフ)

Python
    # 可視化
    fig, ax = plt.subplots()
    summary['conversion_rate'].plot(kind='bar', color=['skyblue', 'salmon'], ax=ax)
    ax.set_ylabel("Conversion Rate")
    st.pyplot(fig)
  • fig, ax = plt.subplots(): グラフを描画するためのfigureaxisを準備します。
  • summary[‘conversion_rate’].plot(kind=’bar’, color=[‘skyblue’, ‘salmon’], ax=ax): 集計したコンバージョン率をバーグラフとして描画します。skybluesalmonの色でAグループとBグループを区別します。
  • ax.set_ylabel(“Conversion Rate”): Y軸に「Conversion Rate」というラベルを設定します。
  • st.pyplot(fig): Streamlitアプリにグラフを表示します。

7. カイ二乗検定を実行

Python
    # カイ二乗検定
    contingency_table = pd.crosstab(df['group'], df['conversion'])
    chi2, p, dof, expected = chi2_contingency(contingency_table)
  • pd.crosstab(df[‘group’], df[‘conversion’]): A/Bグループごとのコンバージョン結果(1または0)をクロス集計表(コンティンジェンシーテーブル)にまとめます。これにより、AグループとBグループごとに「成功(1)」と「失敗(0)」の数がわかります。
  • chi2_contingency(contingency_table): カイ二乗検定を実行し、chi2(カイ二乗統計量)、p(p値)、dof(自由度)、expected(期待値)を得ます。

8. 統計的検定の結果表示

Python
    st.subheader("📈 統計的検定の結果(カイ二乗検定)")
    st.write(f"**p値(p-value)**: `{p:.4f}`")
  • st.subheader(“📈 統計的検定の結果(カイ二乗検定)”): 検定結果の小見出しを表示します。
  • st.write(f”p値(p-value): {p:.4f}“): 計算されたp値を小数点4桁で表示します。p値は結果が偶然の産物である可能性を示す指標です。

9. 結果の解釈

Python
    if p < 0.05:
        st.success("この結果には統計的に有意な差があります(p < 0.05)")
    else:
        st.info("統計的に有意な差は見られません(p ≥ 0.05)")
  • if p < 0.05: p値が0.05未満であれば、「統計的に有意な差がある」と判断します。
  • st.success(): 有意差がある場合、緑色の成功メッセージを表示します。
  • st.info(): 有意差がない場合、青色の情報メッセージを表示します。

10. ファイルがアップロードされていない場合

Python
else:
    st.info("CSVファイルをアップロードしてください")
  • ユーザーがファイルをアップロードしていない場合、このメッセージが表示されます。

ステップ4:アプリの起動

以下のコマンドでStreamlitアプリを起動します。

Bash
streamlit run ab_test_app.py

ブラウザが開いてアプリが表示されます。CSVファイルをアップロードすれば、自動で分析が実行され、統計結果とグラフが表示されます。

補足:入力用CSVデータの作成(ダミーデータ)

上の動画では、以下のプログラムで作成したCSVファイルを入力しています。

Python
import pandas as pd
import numpy as np

# データ数を増やしてサンプルデータを生成
np.random.seed(42)  # 再現性を持たせるためにシードを設定

# AグループとBグループに分けて、コンバージョンの1と0をランダムに生成
n = 100  # サンプル数
data = {
    'group': np.random.choice(['A', 'B'], size=n),
    'conversion': np.random.choice([0, 1], size=n, p=[0.7, 0.3])  # 30%の確率でコンバージョンあり
}

# DataFrameを作成
df = pd.DataFrame(data)

# CSVファイルとして保存
df.to_csv('ab_test_data_large.csv', index=False)

まとめ

このブログでは、以下の内容を学びました:

  • A/Bテストの基本的な考え方
  • 統計的な有意差の重要性とp値の意味
  • Streamlitでの簡単なデータアップロード・表示・グラフ化
  • scipyを使った統計的評価(カイ二乗検定)

Streamlitを使えば、コードが少なくても効果的な分析アプリを作成できます。実務でも学習でも、ぜひ活用してみてください。

参考リンク

最後に書籍のPRです。
24年11月に第3版が発行された「scikit-learn、Keras、TensorFlowによる実践機械学習 第3版」、Aurélien Géron 著。下田、牧、長尾訳。機械学習のトピックスについて手を動かしながら網羅的に学べる書籍です。ぜひ手に取ってみてください。

最後まで読んでいただきありがとうございます。

コメント

タイトルとURLをコピーしました