Excel VBAでクロス表専用のシンプルなカイ二乗検定関数を作ってみた
エクセルExcelでクロス表(i×j表)のカイ二乗検定をしようとすると、元の表の他に「期待値の表」を作らなくてはなりません。
例えば、以下のような(架空の)集計データがあったとき、
ぱっと見なんとなく女性の方が満足度が高そうに見えますが、果たして統計学的に男女で満足度に違いがあると言えるでしょうか?
そんなときにカイ二乗検定を使うことがあります。
エクセルExcelにはカイ二乗検定のp値を計算してくれる関数 CHITEST(と2010以降はCHISQ.TESTも)がありますが、引数に[実測値範囲]と[期待値範囲]を指定する必要があります。そこで、上の表を元に期待値の表を作ります。
[B9:F10]の各セルには、列ごとの合計値を男女比(60:40)で按分した値が格納されています。B9セルを例に数式を表示すると、以下のようになります。
で、最後に任意のセルに以下のように関数と引数を入力すれば、カイ二乗分布の右側確率(p値)を返してくれます。
ちなみに、計算結果は0.0856... でした。有意水準を0.05としたとき有意差なしですね。
「統計学的には男女の満足度に違いがあるとは言えない」ということになります。
本当は、この上さらに検出力を検定しなければならないのかもしれませんが、そこはまだ勉強していません。
ここからが本題です。
CHITEST関数を使う度にいちいち期待値の表を作るのは、あまりにもメンドクサイ!
元の表だけで計算できる関数はないものか?
で、作っちゃいました。以下がそのソースコードになります。*1
'クロス表専用のシンプルなχ二乗検定(右側確率を返す)
Function x_ChiTest(Arg)
Dim o_Row As Integer
Dim o_Clm As Integer
Dim o_R_Sum() As Long
Dim o_C_Sum() As Long
Dim o_Sum As Long
Dim i As Integer
Dim j As Integer
Dim e() As Double
o_Row = Arg.Rows.Count
o_Clm = Arg.Columns.Count
ReDim o_R_Sum(1 To o_Row)
ReDim o_C_Sum(1 To o_Clm)
For i = 1 To o_Row
For j = 1 To o_Clm
o_R_Sum(i) = o_R_Sum(i) + Arg(1).Offset(i - 1, j - 1)
o_C_Sum(j) = o_C_Sum(j) + Arg(1).Offset(i - 1, j - 1)
o_Sum = o_Sum + Arg(1).Offset(i - 1, j - 1)
Next
Next
ReDim e(1 To o_Row, 1 To o_Clm)
For i = 1 To o_Row
For j = 1 To o_Clm
e(i, j) = o_C_Sum(j) * o_R_Sum(i) / o_Sum
Next
Next
x_ChiTest = WorksheetFunction.ChiTest(Arg, e)
End Function
もともと仕事でExcelとAccessは使い倒しているので、VBAはわりと得意なのです。
と言っても、元のクロス表から計算した期待値を配列変数にブッ込んでワークシート関数CHITESTの引数にしただけのお手軽版なので、自慢にもなりませんが。
でも時短にはなります。
使い方は簡単。ソースコードをVBEの標準モジュールにコピペして保存するだけ(Excelアドインとして保存すれば、なお便利に使えます)。
あとは、組み込み関数と同じように関数と引数を入力すればOK。
関数名は、ChiTest の頭に x_ が付きます。引数は[実測値範囲]のみになります。
*1:2017/12/23 コード個所をpre記法に直しました