統計検定の問題を解いていると、有意差etc.. 検定という語句が登場します。
その有意差という言葉で、統計学が最強の学問である | 西内 啓 |本 | 通販 | Amazon に、「ABテストの結果の有意差の判断に統計が使える」 ということが書かれていることを思い出しました。
思い出したことをきっかけで検索すると、以下のような記事がヒットし、なるほどと思っておりました。
記事は実装がR
でしたので、上記のデータを拝借して、 Python で各種検定を実装してみました。
実装した結果を記載します。
参考
実装時に、以下の記事を参考にしました。
-
カイ二乗
-
二項検定
-
t検定
使用するデータについて
A/Bテストに用いられれる統計的検定手法(ロジック)のまとめ&比較 | RCO Ad-Tech Lab Blogに記載されている、コンバージョンが発生したか否かを示すデータを用います。
施策名 / コンバージョンしたか? | YES | NO |
---|---|---|
施策A(改善案サイト) | 454 | 20,933 |
施策B(現状サイト) | 189 | 10,845 |
実装する検定について
こちらも、A/Bテストに用いられれる統計的検定手法(ロジック)のまとめ&比較 | RCO Ad-Tech Lab Blog に記載されている以下検定を Python で実装します。
- χ2検定
- 二項検定
- t検定
また、上記とともに CVR の計算を行います。
CVR の計算
#施策AのCVR
yes = 454
no = 20933
result = yes / (yes + no )
print(result)
0.02122784869313134
#施策BのCVR
yes = 189
no = 10845
result = yes / (yes + no )
print(result)
0.017128874388254486
A のほうがCVRが高いです。
χ2検定 (カイ二乗検定)
R だと、 chisq.test()
で計算できますが、python の場合、scipy.stats.chi2_contingency
で計算できます。
import scipy.stats
import numpy as np
data = np.matrix([ [ 454, 20933 ], [ 189, 10845 ] ])
chi2, p, ddof, expected = scipy.stats.chi2_contingency( data , correction=False)
msg = "Test Statistic: {}\np-value: {}\nDegrees of Freedom: {}\n"
print( msg.format( chi2, p, ddof ) )
print( expected )
Test Statistic: 6.291035173658824
p-value: 0.012135015711322547
Degrees of Freedom: 1
[[ 424.16461553 20962.83538447]
[ 218.83538447 10815.16461553]]
R と同様の結果が得られます。
scipy.stats.chi2_contingency
の引数で指定する、correction
には、補正の有無を指定します。
補正とは、イェイツのカイ二乗検定 - Wikipedia
のことかと思われます。
二項検定
scipy.stats.binom_test
を使用して、計算を行います。
import scipy.stats
import numpy as np
data = np.matrix([ [ 454, 20933 ], [ 189, 10845 ] ])
p_a = np.sum(data, axis=1).item((0, 0)) / data.sum()
print("p_a=", p_a)
conversion_total = np.sum(data, axis=0).item(0, 0)
print("conversion_total=", conversion_total)
conversion_a = data.item(0,0)
print("conversion_a=", conversion_a)
# 確率 p_a の基で、n回試行して、x回 (Aは)yesになった
p_value = scipy.stats.binom_test(x=conversion_a, n=conversion_total, p=p_a, alternative="two-sided")
print("p_value=", p_value)
p_a= 0.659665031924
conversion_total= 643
conversion_a= 454
p_value= 0.0125320280817
t検定
対応しないt検定
の場合は、ttest_ind
を equal_var = False
にして計算を行います。
import scipy.stats
import numpy as np
data = np.matrix([ [ 454, 20933 ], [ 189, 10845 ] ])
# YES を 1、NO を 0 とする、配列を作成する 要素数合計 は 454 + 20933
a = np.hstack((np.repeat(1, data.item(0,0)), np.repeat(0, data.item(0, 1))))
print("a=", a)
# YES を 1、NO を 0 とする、配列を作成する 要素数合計 は 189 + 10845
b = np.hstack((np.repeat(1, data.item(1,0)), np.repeat(0, data.item(1, 1))))
print("b=", b)
# t検定実施 対応するt検定の場合は、equal_var = True
res = scipy.stats.ttest_ind(a, b, equal_var = False)
print("t_value", res[0])
print("p_value", res[1])
a= [1 1 1 ..., 0 0 0]
b= [1 1 1 ..., 0 0 0]
t_value 2.59373998665
p_value 0.00949948651733
R の結果と変わらず、各計算結果を出力することができました。
p_value が小さければ、有意性がある(意味)とだけ覚えておけば良さそうです。
実際に仕事で使う場合は、python での計算というか、Excel や、Google スプレッドシートで式を組んで使用する気もしますので、後日、Google スプレッドシートで式を組んでみようかと思いました。
以上です。
コメント