静粛に、只今統計勉強中

仕事でデータ分析をすることになったバリバリ文系アラフィフのおっさんが、独学で統計の勉強を始めました。

Excel VBAでクロス表専用のシンプルなカイ二乗検定関数を作ってみた

エクセルExcelでクロス表(i×j表)のカイ二乗検定をしようとすると、元の表の他に「期待値の表」を作らなくてはなりません。
例えば、以下のような(架空の)集計データがあったとき、

f:id:cyclo-commuter:20171207150504j:plain

ぱっと見なんとなく女性の方が満足度が高そうに見えますが、果たして統計学的に男女で満足度に違いがあると言えるでしょうか?

そんなときにカイ二乗検定を使うことがあります。

エクセルExcelにはカイ二乗検定のp値を計算してくれる関数 CHITEST(と2010以降はCHISQ.TESTも)がありますが、引数に[実測値範囲]と[期待値範囲]を指定する必要があります。そこで、上の表を元に期待値の表を作ります。

f:id:cyclo-commuter:20171207150945j:plain

[B9:F10]の各セルには、列ごとの合計値を男女比(60:40)で按分した値が格納されています。B9セルを例に数式を表示すると、以下のようになります。

f:id:cyclo-commuter:20171207151533j:plain

で、最後に任意のセルに以下のように関数と引数を入力すれば、カイ二乗分布の右側確率(P)を返してくれます。

f:id:cyclo-commuter:20171207151945j:plain

ちなみに、計算結果は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

もともと仕事でExcelAccessは使い倒しているので、VBAはわりと得意なのです。
と言っても、元のクロス表から計算した期待値を配列変数にブッ込んでワークシート関数CHITESTの引数にしただけのお手軽版なので、自慢にもなりませんが。
でも時短にはなります。

使い方は簡単。ソースコードをVBEの標準モジュールにコピペして保存するだけ(Excelアドインとして保存すれば、なお便利に使えます)。
あとは、組み込み関数と同じように関数と引数を入力すればOK。

f:id:cyclo-commuter:20171207162702j:plain

関数名は、ChiTest の頭に x_ が付きます。引数は[実測値範囲]のみになります。

*1:2017/12/23 コード個所をpre記法に直しました