http://localhost:8888/notebooks/... Python で統計学を学ぶ (5) この内容は山田 杉澤 村井 (2008) R によるやさしい統計学 (http://shop.ohmsha.co.jp/shop /shopdetail.html?brandcode=000000001781&search=978-4-274-06710-5&sort=) を参考にしています この講義では 2 つの平均値を比較する をとりあげます 具体的には 2 つの平均値を比較する方法の学習 つまり (1) 独立な 2 群の平均値差の検定と (2) 対応のある 2 群の平均値差の検定 について学びます 学習項目です : 2 つの平均値を比較するケース独立な 2 群の t 検定 t 検定の前提条件対応のある t 検定関数のまとめ演習問題 2 つの平均値を比較するケース物語 : ある心理学の教授は考えました 今までの講義では教育効果があがらない そこで指導方法を変えてみよう ( 例えば アクティブラーニングを取り入れる 毎回宿題を出して学習を促進する ) 一方 試験では今までと同程度の問題を出して 指導方法を変えたことによる効果があったか 検証することにしました 本当に効果があったか調べるには 今までの指導法による試験のデータと 指導方法を変えた後の試験のデータ ( 指導法データ と呼びます ) を比較すればよいのだが 具体的にはどうすればよいのだろう??? 2 つの平均値を比較することが必要とされる場合 : 独立な 2 群の t 検定 ( 独立な 2 群 とは何か に注意 ) 男女で心理学テストの平均値に差があるかどうか統計の好き嫌いで統計テストの平均値に差があるか --- 統計が好きである人の統計テストの点数の分布と 統計が嫌いな人の統計テストの点数の分布の比較対応のある 2 群の t 検定 ( 何と何が対応しているか に注意 ) 同じ対象者に対して指導法の違いが成績に影響するかどうか 2 群の標本から 2 つの群の母平均の比較を行うことが目的 1 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... 独立な 2 群の t 検定 2 群が独立である具体的な例 : 男女それぞれの心理学テストの成績 統計が好きな人と嫌いな人それぞれの統計学テストの成績 というように 2 群がそれぞれ別々の標本から得られたデータが対象 --- t 検定を実施するための条件については あとで述べる t 検定の前提条件を参照のこと μ 1, μ 2 σ 2 X 1, X 2 X 1 N( μ 1, σ 2 ) X 2 N( μ 2, σ 2 ) 平均がそれぞれ かつ分散が等しい 正規分布に従う母集団から無作為抽出された標本を 考える : 式で書くと, その平均値の差 ( ここでn 1 とn 2 はそれぞれの群のサンプルサイズとする ) X 1 X 2 はやはり正規分布に従う : これを標準化する ( 問題 : 標準化とは?): X 1 X 2 N( μ 1 μ 2, σ 2 1 1 ( + )) n 1 X 1 X 2 ( μ 1 μ 2 ) 1 1 σ n 1 + n 2 ここで母分散 σ 2 が未知であるなら標本から推定する : σ 2 pooled = ( ここで とはそれぞれの群の不偏分散 --- 問題 : とを合わせた標本の不偏分散の値とこのσ 2 pooled との関係は?) n 2 N(0, 1) ( n 1 1) σ 2 1 + ( n 2 1) σ 2 2 n 1 + n 2 2 σ 2 1 σ 2 2 X 1 X 2 この値によって次の検定統計量を導く : t = こうして導かれた検定統計量 t の標本分布は 帰無仮説 df = n 1 + n 2 2 X 1 X 2 ( n 1 1) σ 2 1+( n 2 1) σ 2 2 1 1 ( + ) n 1 + n 2 2 n 1 n 2 H 0 : μ 1 = μ 2 のもとで 自由度のt 分布にしたがう この検定統計量を用いて 2つの平均値の差に関する検定を行うことができるようになる ( 問題 : 対立仮説はどうなる?): Python を使った実習例題 : 統計テスト 1 (StatTest1) の得点の平均値に男女で有意な差があるかどうかを有意水準 5% 両側検定で検定せよ StatTest1Male = np.array([6,10,6,10,5,3,5,9,3,3]) StatTest1FeMale = np.array([11,6,11,9,7,5,8,7,7,9]) 2 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... 次のステップで行う : 1. 帰無仮説と対立仮説をたてる : 帰無仮説 (2つの母平均は等しい) 対立仮説 H 1 : μ 1 μ 2 (2つの母平均は等しくない) 2. 検定統計量の選択 : X 1 X 2 を検定統計量とする これは 自由度のt 分布に従う 3. 有意水準の決定 : 両側検定で 有意水準 5% つまり 4. 検定統計量の実現値の計算 : まず 2つの標本の平均と不偏分散を求め print(np.mean(stattest1male)) 6.0 print(np.mean(stattest1female)) 8.0 print(np.var(stattest1male, ddof=1) 7.777778 print(np.var(stattest1female, ddof = 1)) 4.0 次に プール標準偏差 (PooledStd) σ pooled を求める n1 = len(stattest1male) n2 = len(stattest1female) PooledStd = (((n1-1)*np.var(stattest1male,ddof=1)+(n2-1)*np.var(stattest1female,ddof=1)) / (n1+n2-2))**0.5 print(pooledstd) 2.426703 最後に検定統計量の実現値を計算する : H 0 : μ 1 = μ 2 t = ( n 1 1) σ 2 1+( n 2 1) σ 2 2 1 1 ( + ) n 1 + n 2 2 n 1 n 2 df = n 1 + n 2α 2 = 0.05 tdivider =PooledStd * (1.0/n1+1.0/n2)**0.5 tdividend = np.mean(stattest1male)-np.mean(stattest1female) t = tdividend / tdivider # 検定統計量 -1.842885 検定統計量の実現値がt = -1.84と求まった 5. 帰無仮説の棄却か採択かの決定 : 帰無仮説によればこの検定統計量は自由度のt 分布に従う 有意水準は5% 両側検定の時の棄却域を求める df = 10 + 10 2 = 18 import scipy.stats as st st.t.ppf(0.025,18) # 検定統計量 df=18 下側確率 0.05/2 = 0.025となる tの値を求める -2.100922 # 下側確率であるから この値よりもt 値が小さければ棄却される st.t.ppf(0.975,18) # df=18 上側確率 1-0.05/2 = 0.975となるtの値を求める 2.100922 # 上側確率であるから この値よりもt 値が大きければ棄却される t < 2.10 t > 2.10 この結果 棄却域はまたはとなるので tの値は棄却域に入らないため 帰無仮説は棄却されない ゆえに 検定の結果は 有意水準 5% で有意差が見られなかった となるなおcdf 関数を用いて 直接 p 値を求めることもできる : st.t.cdf(-1.842885,18) # 下側確率 0.04093903 # 下側確率とすれば p 値は0.04という値 ( < 0.05) 2*st.t.cdf(-1.842885,18) # 両側検定なので2 倍する 0.08187807 3 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... In [12]: # 以上の実行 from future import division StatTest1Male = np.array([6,10,6,10,5,3,5,9,3,3]) StatTest1Female = np.array([11,6,11,9,7,5,8,7,7,9]) print(np.mean(stattest1male)) print(np.mean(stattest1female)) print(np.var(stattest1male, ddof=1)) print(np.var(stattest1female, ddof = 1)) 6.0 8.0 7.77777777778 4.0 In [13]: n1 = len(stattest1male) n2 = len(stattest1female) PooledStd = (((n1-1)*np.var(stattest1male,ddof=1)+(n2-1)*np.var(stattest1female,ddof=1)) / ( print(pooledstd) 2.42670329643 In [16]: tdivider =PooledStd*(1.0/n1+1.0/n2)**0.5 tdividend = np.mean(stattest1male)-np.mean(stattest1female) t = tdividend / tdivider # 検定統計量 print(t) -1.8428853505 In [19]: import scipy.stats as st print(st.t.ppf(0.025,18) ) # 検定統計量 df=18 下側確率 0.05/2 = 0.025となるtの値を # 下側確率であるから この値よりもt 値が小さければ棄却される print(st.t.ppf(0.975,18)) # df=18 上側確率 1-0.05/2 = 0.975となるtの値を求める # 上側確率であるから この値よりもt 値が大きければ棄却される -2.10092204024 2.10092204024 In [21]: print(st.t.cdf(-1.842885,18)) # 下側確率 # 下側確率とすれば p 値は0.04という値 ( < 0.05) print(2*st.t.cdf(-1.842885,18)) # 両側検定なので2 倍する # 両側検定であるから2 倍したp 値は0.08という値 (> 0.05) 0.0409390340087 0.0818780680175 In [ ]: help(st.ttest_ind) In [30]: Out[30]: st.ttest_ind(stattest1male,stattest1female) Ttest_indResult(statistic=-1.8428853505018534, pvalue=0.081878014624106793) 課題 5-1 独立な2 群のt 検定では それぞれN( μ 1, σ 2 ) とN( μ 2, σ 2 ) に従う2つの標本 X 1 とX 2 に対し その平均値の差がN( μ 1 μ 2, σ 2 ( 1 1 n + ) に従う ということが前提となっていた ( ただしここで はそれぞれの 1 n 2 n 1, n 2 標本のサイズ ) このことを 今まで学んだことから示せ [ ヒント ] 正規分布に従う標本平均の標本分布がどのような分布に従うかは前項の 標本分布を求める 節 (Python-statistics3.ipynb#makingSample) で述べられている また それぞれ正規分布にしたがう 2 つの標本データの和 ( 差 ) がどのような分布に従うかは Python で確率を学ぶ の主要な確率分布の項 (Intro2Probab.ipynb#NormalDistribution) で述べられている これらを組み合わせえて考えよ 4 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... 解答欄 課題 5-2 今の例題の計算において 次のものは何を計算しているのか 式と照らしあわせて確認せよ : (1) プール標準偏差,(2) t 分母 (3) t 分子 (4)t 統計量 σ pooled 解答欄 t 検定の前提条件 t 検定を実行するには次の 3 つの条件が必要 1. 標本が無作為に行われていること ( 無作為抽出 ) 2. 母集団の分布が正規分布にしたがっていること ( 正規性 ) 3. 2 つの母集団の分散が等質であること ( 分散の等質性 ) 分散の等質性の検定 2 群の分散が等しいことを この 2 群の分散は等質である といいます t 検定では 2 群の分散が等質であることが前提です それには 分散の等質性の検定 を行う必要があります これは検定統計量を F としているため F 検定とも呼ばれています まずそれぞれの分散 ( とする ) を求め その比 ( ) を検定統計量とします ここで 分散の大きい方 を分母にとる必要があります ( 今の例ではと仮定した ) この値は 2 群のサイズをそれぞれと すると 分子の自由度 分母の自由度のF 分布に従うので scipy.stats.fモジュールのcdf 関数によってp 値を求めます ( このとき 帰無仮説は 等質である 対立仮説は 等質ではない となることに注意 ) 以下では例を用いて示します : σ1 2, σ 2 2 F = σ 1 2 σ 2 2 σ 2 > σ 1 F n 1, n 2 df 1 =n 1 1 df 2 =n 2 1 In [1]: import scipy.stats as st ClassA = np.array([54,55,52,48,50,38,41,40,53,52]) ClassB = np.array([67,63,50,60,61,69,43,58,36,29]) print("variance of ClassA = %f, ClassB = %f" % (np.var(classa), np.var(classb))) variance of ClassA = 35.810000, ClassB = 166.040000 In [32]: # ClassBの分散が大きいので それを分母にとる F = np.var(classa)/np.var(classb) print(st.f.cdf(f, len(classa)-1, len(classb)-1)*2) 0.0160295541215 # 両側検定のため 2 倍する 5 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... この例では p 値が 0.03 であるため 帰無仮説が棄却されます つまりこの例では 2 つの変数の分散が等質であるという仮定は成り立ちません そのため この 2 つの変数に対しては t 検定ができない ということになります その場合でも 2 つの群の平均値の比較の検定は可能です その一つの方法が 次で紹介する Welch( ウェルチ ) の検定です [ なぜ分散が等質でないと判断されたか ] 今の説明で p 値が 0.03であるため 帰無仮説が棄却された ( つまりこの例では2つの変数の分散が等質であるという仮定は成り立たない ) という点に疑問を持った人のために 解説します ここで行ったのは 2つの群が等質である ことを示すための検定ではないのです 行ったのは 等質でない ( これが 対立仮説 帰無仮説は 等質である ) ことの検定でした そして有意水準を5% とすると p < 0.05ですから 帰無仮説が棄却され 対立仮説が採択されたのです つまり この例では2つの変数の分散が等質であるという仮定は成り立たない という結論になります In [ ]: help(st.f.cdf) Welch の検定 母分散が等質でないときは t 検定は使えないので Welch 検定を使う ---st.ttest_ind 関数で equal_var=false というオプションをつけて実行します : In [33]: Out[33]: st.ttest_ind(classa, ClassB, equal_var=false) Ttest_indResult(statistic=-1.1191356939670116, pvalue=0.28378771746038012) この結果は p 値が 0.28 なので 帰無仮説が棄却されない つまりクラス A とクラス B の平均に有意な差はない という結論になります 課題 5-3 独立な 2 群の t 検定の例題のデータ つまり StatTest1Male と StatTest1Female のデータに対して 分散の等質性の検定を行え また分散の等質性が成り立たないと仮定して Welch の検定を行い その結果を前の例題の結果と比較せよ In [ ]: 6 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... 対応のある t 検定 対応のあるデータ : 例えば 同じ被験者について複数の測定が行われている場合例 : 統計の指導を受ける前と後のテスト得点である 統計テスト 1 と 統計テスト 2 対応あるデータについては 独立な 2 群の t 検定ではない別の方法が必要です 対応のあるデータでは 変化量 ( あるいは差得 ) を考えます 統計テスト1の得点を 統計テスト2の得点を 変化量( 差得点 ) をDとすれば X 1 X 2 D = X 2 X 1 X 1, X 1, D D = X 2 X 1 さらに これらの標本平均の間にはという関係がなりたちます D N( μ D, σ 2 σd D) n D N( μ D, 2 ) 差得点と仮定 s, データ数をとすると その標本平均 n となります この標本分布を標準化すると D μ D Z = N(0, 1) σ D / n ここで σ D が未知なので これを標本から求めた標準偏差 σ D で代用すると t = D μ D σ D / n は自由度 のt 分布にしたがいます df = n 1 7 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... Pythonを使った実習例題 : 指導の前後に行った 統計テスト1 (StatTest1) と 統計テスト2 (StatTest2) で有意な差があるかどうかを有意水準 5% 両側検定で検定せよ StatTest1 = np.array([6,10,6,10,5,3,5,9,3,3,11,6,11,9,7,5,8,7,7,9]) StatTest2 = np.array([10,13,8,15,8,6,9,10,7,3,18,14,18,11,12,5,7,12,7,7]) 次のステップで行う : 1. 帰無仮説と対立仮説をたてる : 帰無仮説 H 0 : μ D = 0(2つのテストの差の母平均は0) 対立仮説 H 1 : μ D 0 (2つのテストの差の母平均は0) ではない ) 2. 検定統計量の選択 : t = D μ D を検定統計量とする ( 帰無仮説の下ではμ なので σ D / n D = 0 t = D σ D / n これは 自由度 df = n 1 のt 分布に従う 3. 有意水準の決定 : 両側検定で 有意水準 5% つまりα = 0.05 4. 検定統計量の実現値の計算 : Difference = StatTest2 - StatTest1 print(np.std(difference, ddof=1)) 2.772041 tdivider = np.std(difference, ddof=1)/(len(difference))**0.5 tdividend = np.mean(difference) t = tdividend / tdivider print(t) 4.839903 この結果 検定統計量の実現値は t= 4.84 5. 帰無仮説の棄却か採択かの決定 : 帰無仮説によればこの検定統計量は自由度分布に従う 有意水準は5% 両側検定の時の棄却域を求める st.t.ppf(0.025,19) # 検定統計量 df=19 下側確率 0.05/2 = 0.025となるtの値を求める -2.093024 # 下側確率であるから この値よりもt 値が小さければ棄却される st.t.ppf(0.975,19) # df=19 上側確率 1-0.05/2 = 0.975となるtの値を求める 2.093024 # 上側確率であるから この値よりもt 値が大きければ棄却される t < 2.09 t > 2.09 df = 20 1 = 19 この結果 棄却域はまたはとなるので tの値は棄却域に入るため 帰無仮説は棄却される ゆえに 検定の結果は 5% 水準で有意差が見られた となるなお scipy.statsモジュールのttest_rel 関数によっても対応のあるt 検定を求めることができる : st.ttest_rel(stattest1, StatTest2) Ttest_relResult(statistic=-4.8399026368560945, pvalue=0.0001137879500886128 6) # 検定統計量と p 値 この結果 p 値が 0.0001 という小さな値であるので 帰無仮説が棄却され 検定の結果は 有意水準 5% で 統計テスト 1 と統計テスト 2 では有意な差があった となる の t In [34]: import scipy.stats as st StatTest1 = np.array([6,10,6,10,5,3,5,9,3,3,11,6,11,9,7,5,8,7,7,9]) StatTest2 = np.array([10,13,8,15,8,6,9,10,7,3,18,14,18,11,12,5,7,12,7,7]) 8 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... In [36]: Difference = StatTest2 - StatTest1 print(np.std(difference, ddof=1)) tdivider = np.std(difference, ddof=1)/(len(difference))**0.5 tdividend = np.mean(difference) t = tdividend / tdivider print(t) 2.77204085942 4.83990263686 In [37]: print(st.t.ppf(0.025,19)) # 検定統計量 df=19 下側確率 0.05/2 = 0.025となるtの値を求める # 下側確率であるから この値よりもt 値が小さければ棄却される print(st.t.ppf(0.975,19) ) # df=19 上側確率 1-0.05/2 = 0.975となるtの値を求める # 上側確率であるから この値よりもt 値が大きければ棄却される -2.09302405441 2.09302405441 In [38]: Out[38]: st.ttest_rel(stattest1, StatTest2) Ttest_relResult(statistic=-4.8399026368560945, pvalue=0.00011378795008861286) 課題 5-4 今の例題の計算において 次のものは何を計算しているのか 式と照らしあわせて確認せよ : (1) 変化量,(2) 分母 t (3) 分子 t (4) t 統計量 解答欄 課題 5-5 今の例題のデータに対して 対応なしの場合の検定 を行え そして対応ありの場合と対応なしの場合では どのような違いがあるか 具体的に述べよ 解答欄 関数のまとめ注 : numpy を np, numpy.random を random matplotlib.pyplot を plt pandas を pd scipy.stats を st と略記する 目的関数名とモジュール使い方 分散の等質性の検定 (F 検定 ) における p 値 独立な 2 群の検定 Welch の検定 ( 分散が等質でない場合 ) 対応のある t 検定 st.f.cdf(f, 分子の自由度, 分母の自由度 ) st.ttest_ind( データ 1, データ 2) st.ttest_ind( データ 1, データ 2, equal_var=false) st.ttest_rel( データ 1, データ 2) st.f.cdf(np.var(classa)/np.var(classb),len(classa)-1,len(classb)-1) # ClassA と ClassB の分散の等質性の検定のための p 値 (np.var(b) > np.var(a) と仮定 ) st.ttest_ind(stattest1male,stattest1female) st.ttest_ind(classa, ClassB, equal_var=false) st.ttest_rel(stattest1, StatTest2) 9 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... 演習問題 5 演習問題 5-1 以下は 統計学が好きな人の得点と嫌いな人の得点のデータである 統計学が好きか嫌いかという 2 群について 平均値に有意な差があるかどうかを 有意水準 5% の両側検定で調べよ StatLovers = np.array([6, 10, 6, 10, 11, 6, 11, 7]) StatHaters = np.array([5, 3, 5, 9, 3, 3, 9, 5, 8, 7, 7, 9]) [ ヒント ] 統計学好き (StatLovers) と 統計学嫌い (StatHaters) の 2 変数は 分散が等質かどうか不明である そこで まず (1) 分散の等質性の検定を行い その結果 (2a) 分散が等質であれば t 検定を行い (2b) 分散が等質でなければ Welch の検定を行う In [39]: StatLovers = np.array([6, 10, 6, 10, 11, 6, 11, 7]) StatHaters = np.array([5, 3, 5, 9, 3, 3, 9, 5, 8, 7, 7, 9]) 演習問題 5-2 以下は 心理学テストにおける 男と女のデータである 男女で平均値に有意な差があるかどうかを 有意水準 5% の両側検定で調べよ PsycTestMale= np.array([13, 14, 7, 12, 10, 6, 8, 15, 4, 14]) PsycTestFemale = np.array([9, 6, 10, 12, 5, 12, 8, 8, 12, 15]) [ ヒント ] 心理学テスト男 (PsycTestMale) と 心理学テスト女 (PsycTestFemale) の 2 変数は 分散が等質かどうか不明である そこで まず (1) 分散の等質性の検定を行い その結果 (2a) 分散が等質であれば t 検定を行い (2b) 分散が等質でなければ Welch の検定を行う In [40]: PsycTestMale= np.array([13, 14, 7, 12, 10, 6, 8, 15, 4, 14]) PsycTestFemale = np.array([9, 6, 10, 12, 5, 12, 8, 8, 12, 15]) 演習問題 5-3 以下はビデオ視聴によるダイエットプログラムに参加した 10 名の プログラム参加前後の体重のデータである ( 単位は kg) このデータから ダイエットプログラムは効果があったと言えるかどうかを判定せよ 有意水準を 5% 両側検定とする Before = np.array([61, 50, 41, 55, 51, 48, 46, 55, 65, 70]) After = np.array([59, 48, 33, 54, 47, 52, 38, 50, 64, 63]) [ ヒント ] 同じ人についてのプログラム参加前 (Before) と後 (After) のデータなので 対応のある t 検定 を行う In [ ]: Before = np.array([61, 50, 41, 55, 51, 48, 46, 55, 65, 70]) After = np.array([59, 48, 33, 54, 47, 52, 38, 50, 64, 63]) 10 / 11 2018/01/11 10:24
http://localhost:8888/notebooks/... 演習問題 5-4 shidouhou.csv (http://lang.sist.chukyo-u.ac.jp/classes/pythonprobstat/sampledata/shidouhou.csv) は区切り記号がコンマの CSV 形式のファイルである このデータをデータフレームとして読み込み 統計テスト 1 と心理学テストの母平均に差があるかどうか 検定を行え [ 参考 ] 区切り記号がコンマの csv ファイルを読み込み その内容をデータフレームとして取り込むには pandas モジュールの read_csv 関数を用いる もっとも中にはちゃんと読み込めないこともあるので ファイルの中身と読み込み形式とを確認すること そして読み込めない場合は 区切り記号を適切なものにセットしたりすることも考えよう In [ ]: 11 / 11 2018/01/11 10:24