📉

データ分析 python 2群間の代表値の検定:対応のある2標本のt検定

2024/09/07に公開

以前まとめた2群間の代表値の検定について、具体的な手法を簡単にまとめてみます。
python + google colaboratory で 実行しています。
https://zenn.dev/longbridge/articles/b5abd84b331381

テーマ

あるカフェチェーンでは、新しいコーヒーメニューが売上にどの程度影響を与えるかを検討しています。
そこで、エリア内の10店舗を無作為に選び、新メニュー導入前と導入後の1週間の売上データを比較しました。
新メニューの導入は売上に有意な影響を与えたと言えるでしょうか?

使用したデータ

カフェチェーンの売上データを想定しています。

店舗番号 導入前売上 導入後売上
1 524.84 513.61
2 493.09 496.78
3 532.38 537.24
4 576.15 574.12
5 488.29 495.87
6 476.79 481.95
7 476.78 481.22
8 582.00 579.38
9 558.40 570.67
10 518.51 518.22

前準備

グラフに日本語ラベルを表示できるように japanize-matplotlib をインストールします。

!pip install -q japanize-matplotlib

必要のライブラリをインポートして、使用するデータを読み込んでおきます。

import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib
import seaborn as sns
from scipy import stats

# データ読込
df = pd.read_csv('/content/drive/MyDrive/cofee_sales.csv')
df

導入前売上と導入後売上の代表値を確認

導入前と導入後の平均値を確認する
df.mean()

導入前と導入後の中央値を確認する
df.median()

平均値にも中央値にも、新メニュー導入前と導入後に差があります。
この差は標本集団だけの差なのか、母集団でも意味ある差なのかを検定していきます。

使用する検定を決定する

1.正規性を視覚的に確認する

まずは使用する検定を特定するために、データが正規性に従っているかを確認します。
先ほど確認した平均値と中央値の値がほぼ一緒なので、正規分布に従っていそうです。

導入前と導入後の値をヒストグラムで可視化して正規性を確認してみます。

plt.figure(figsize=(10, 4))

plt.subplot(1, 2, 1)
sns.histplot(df['導入前売上'], kde=True)

plt.subplot(1, 2, 2)
sns.histplot(df['導入後売上'], kde=True)

グラフからも正規分布に従っていることが確認できます。

2.正規性を統計的に確認

視覚だけでなく統計的にも正規分布に従っているかを確認します。

正規性を確認する代表的な検定方法には下記のような検定があります。

  • シャピロ・ウィルク検定(S-W検定)
    • 小さいデータセットに適しています
    • scipy の shapiroメソッドを使用
  • コルモゴロフ・スミルノフ検定(K-S検定)
    • 広く使われています
    • scipy の kstestメソッドを使用
  • Anderson-Darling検定
    • シャピロ・ウィルク検定よりも詳細な正規性の確認ができます。
  • Q-Qプロット
    • 視覚的にデータの正規性を確認するのに便利です。

今回はデータセットが小さいので シャピロ・ウィルク検定 を使用して正規性を検定します。

シャピロ・ウィルク検定 は scipy の shapiroメソッドを使用します。
帰無仮説:正規分布である
対立仮説:正規分布でない
P値が0.05より小さい場合、帰無仮説を棄却し、データは正規分布に従っていないと判断します。

from scipy import stats
stats.shapiro(データ)

ちなみに、データセットが多い場合は コルモゴロフ・スミルノフ検定 を使用します
コルモゴロフ・スミルノフ検定 は scipy の kstestメソッドを使用します。
正規性を検定する際は kstest メソッドの第二引数に'"norm"'を指定します。

from scipy import stats
stats.kstest(データ, "norm")
正規性を検定する

それでは、実際に導入前売上 と 導入後売上 の それぞれのデータを検定してみます。

導入前データの正規性を検定する

stats.shapiro(df['導入前売上'])

ShapiroResult(statistic=0.9898833815158521, pvalue=0.6551676754215174)

P値(pvalue)=0.655 と 優位水準を0.05を上回っていますので、帰無仮説を棄却できず
導入前売上データは正規分布に従っていると判断します。

導入後データの正規性を検定する

stats.shapiro(df['導入後売上'])

ShapiroResult(statistic=0.9942133018173435, pvalue=0.9493446288472879)

P値(pvalue)=0.949 と 優位水準を0.05を上回っていますので、帰無仮説を棄却できず
導入後売上データも正規分布に従っていると判断します。

3.使用する検定

導入前売上データ と 導入後売上データ の両方が、正規分布に従うので「パラメトリック検定」で
今回は、同じ対象の前後比較にですので「対応あり」データになります。
よって、今回使う検定は「対応のある2標本のt検定」となります。

対応のある2標本のt検定は scipy の ttest_rel メソッドを使用します。
ttest_rel は「related(関連がある)」を意味しています。

使い方

from scipy import stats
stats.ttest_rel(df['導入前売上'], df['導入後売上'])

検定を行う

それでは実際に検定を行います。

1.仮説立て
  • 帰無仮説:2群間の平均値に有意な差はない
  • 対立仮説:2群間の平均値に有意な差はある
2.優位水準
  • 5%
3.判定
stats.ttest_rel(df['導入前売上'], df['導入後売上'])

出力結果

TtestResult(statistic=-7.22442774324596, pvalue=1.0553359354605914e-10, df=99)

P値(pvalue)は「1.055e-10」と0.01より十分に小さいので
有意水準 > P値 となり 帰無仮説を棄却し、対立仮説を採用します。

4.結論

新メニュー導入は売上に有意な影響を与えていると判断できる。

以上で、今回の検定は終了です。

Discussion