次のようなシナリオを想定します。
関東圏内を中心としたチェーン店 D フランチャイズでは都市ごとの店舗で複数の商品を扱っています。このたび、市場に投入した新商品 A と B について、人気の 2 店舗での販売状況を調べることになりました。
クロス集計表を作成する
本番システム運用チームの協力を得て販売管理システムから 2 店舗の新商品の販売ログデータを入手することができました。これはその架空の販売管理システムのログデータの一部です。並列分散システムから出力したもので、実際にはタブ区切りのテキストデータとなっているものとします。
店舗 | 売上 |
---|---|
店舗 1 | 商品 A |
店舗 2 | 商品 A |
店舗 2 | 商品 B |
店舗 1 | 商品 A |
店舗 1 | 商品 B |
店舗 1 | 商品 B |
店舗 2 | 商品 A |
店舗 1 | 商品 A |
クロス集計表は離散変数同士の関連を検討する際に用いられます。 pandas を利用するとクロス集計をいとも簡単におこなうことができます。
import pandas as pd
# タブ区切りのテキストデータを読み込む
data = pd.read_csv("data.txt", sep="\t")
# クロス集計をする
crossed = pd.crosstab(data.A, data.B)
#=>
# A B
#store_1 435 165
#store_2 265 135
クロス集計表ができました。
2 つの変数の関連において、どちらかの変数が、もうひとつの変数の原因となっている場合に、原因となる側の変数を 独立変数 (independent variable) 、もう一方の結果となる変数を 従属変数 (dependent variable) と言います。これは 2 変数の間に因果関係があると考えられるときに生じます。つまりクロス集計表で提示されるのは、原則として独立変数の側を基準とした各カテゴリーの値です。
科学研究の多くは、突き詰めればこのように複数の変数の因果関係を確かめたり、探したりするといったことに行き着く場合が多々あります。厳密な意味で 2 つの変数が因果関係があると言い切るためには、変数 A と変数 B が次の 3 つの条件を満たす必要があります。
- 変数 A が変数 B より先に発生している (時間先行性)
- 変数 A と変数 B が共変関係にある (相関性)
- 変数 A と変数 B が疑似相関ではない (非疑似相関性)
カイ二乗検定をおこなう
2 つの離散変数にまったく関連が無い、つまりは変数の値の一方が変化しても他方の変数の分布が変化しない状態のことを統計用語で 独立 (independence) と言います。
独立という状態におけるそれぞれのセルの度数を 期待度数 (expected frequency) と言い次式で表されます。
F_{ij} = \frac {n_i × n_j} n
さて今回の新商品 A と B について、店舗ごとの売上の差異は無いのでしょうか。小集団で標本誤差が未知の場合は検定統計量として t 値を、確率分布としては t 検定を用います。それに対してクロス集計表の仮説検定では通常カイ二乗分布を用います。
以前に説明した内容に基づき、帰無仮説は次のようになります。
仮説 | 説明 |
---|---|
帰無仮説 | 母集団において 2 つの変数は独立に分布し、関連していない |
対立仮説 | 母集団において 2 つの変数は独立に分布しておらず、関連している |
カイ二乗分布は自由度によってその曲線が大きく変化します。その値は、自由度 = (行数 - 1) × (列数 -1) で求まります。有意水準 α は 5% とします。
店舗 | 商品 A | 商品 B |
---|---|---|
店舗 1 | 435 | 165 |
店舗 2 | 265 | 135 |
このクロス集計表に対してカイ二乗検定をおこないます。
SciPy で行列に対するカイ二乗検定の関数が見つからなかったというブログ記事もありますが、これは stats.chi2_contingency 関数でおこなうことができます。自力で実装する必要はありません。
import scipy as sp
import scipy.stats
x2, p, dof, expected = sp.stats.chi2_contingency(crossed)
print("カイ二乗値は %(x2)s" %locals() )
print("確率は %(p)s" %locals() )
print("自由度は %(dof)s" %locals() )
print( expected )
if p < 0.05:
print("有意な差があります")
else:
print("有意な差がありません")
#=>
# カイ二乗値は 4.17162698413
# 確率は 0.041106308266
# 自由度は 1
# [[ 420. 280.]
# [ 180. 120.]]
# 有意な差があります
店舗 1 のほうが商品 B の売上の割合が小さいことが 95% の信頼度で言えることがわかりました。
参考
カイ二乗検定をはじめとする検定については以下のサイトがとても参考になります。ぜひとも参考にしてみてください。
ハンバーガー統計学にようこそ!
http://kogolab.chillout.jp/elearn/hamburger/index.html