裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

Julia: HypothesisTests.PowerDivergenceTest() の問題点

2022年02月04日 | ブログラミング

Julia の HypothesisTests.PowerDivergenceTest() は問題がある。

対象とする分割表に,度数が 0 のセルがあると不適切な(役に立たない)結果を返す。

julia> x = [4 5 2 0; 0 7 6 1; 1 0 3 1]
3×4 Matrix{Int64}:
 4  5  2  0
 0  7  6  1
 1  0  3  1

julia> using HypothesisTests

julia> result = PowerDivergenceTest(x, lambda=0.0);

julia> println(result.stat)
NaN

julia> println(pvalue(result))
NaN

そこで,以下のような関数を書く。

julia> function PDTsummary(result::PowerDivergenceTest; resid::Bool=false)
           # 結果を簡潔に表示するための関数
           function printmatrix(name, x)
               println("\n$name")
               Base.print_matrix(stdout, round.(x, digits=5), "", "   ", "\n")
           end
           println("chisq. = $(round(result.stat, digits=5)), df = $(result.df), p.value = $(round(pvalue(result), digits=5))")
           if resid
               printmatrix("residuals", result.residuals)
               printmatrix("standardized residuals", result.stdresiduals)
           end
       end
PDTsummary (generic function with 1 method)

julia> function g2stat(x, nrows, ncols, n, correct)
           # セルに 0 があっても正しい答えを出す
           # correct=true で,連続性の補正も行うことができる
           ln(n) = n .== 0 ? 0 : n .* log.(n)
           n = sum(x) # 全サンプルサイズ
           n1 = sum(x, dims=2) # 行和
           n2 = sum(x, dims=1) # 列和
           G2 = 2*(sum(ln.(x)) - sum(ln.(n1)) - sum(ln.(n2)) + ln(n)) # G 統計量
           correct && (G2 /= 1 + (n * sum(1 ./ n1) - 1) * (n * sum(1 ./ n2) - 1) / (6n * nrows * ncols)) # 連続性の補正
           df = (nrows - 1) * (ncols - 1) # G の自由度
           G2, df
       end
g2stat (generic function with 1 method)

julia> function chisq_test(x::AbstractMatrix{T}; correct::Bool=false, resid::Bool=false, lambda::Float64=1.0) where T<:Integer
           # 分割表を入力してχ二乗検定,G2 検定
           nrows, ncols = size(x)
           n = sum(x)
           if lambda == 1.0 && correct && nrows == 2 && ncols == 2
               a, c, b, d = x
               stat = n*max(0, abs(a*d - b*c) - 0.5n)^2 / ((a+b)*(c+d)*(a+c)*(b+d))
               result = PowerDivergenceTest(lambda, ones(4), stat, 1, x, n, ones(4), x, x, x)
           elseif lambda == 1.0
               result = PowerDivergenceTest(x; lambda)
           elseif lambda == 0.0
               G2, df = g2stat(x, nrows, ncols, n, correct)
               vec = ones(nrows*ncols)
               mat = reshape(vec, nrows, ncols)
               result = PowerDivergenceTest(lambda, vec, G2, df, mat, n, vec, mat,  mat, mat)
           end
           PDTsummary(result; resid)
       end
chisq_test (generic function with 1 method)

julia> function G2_test(x::AbstractMatrix{T}; correct::Bool=false, resid::Bool=false) where T<:Integer
           chisq_test(x; correct, resid, lambda=0.0)
       end
G2_test (generic function with 1 method)

これで,

julia> G2_test(x)
chisq. = 15.36459, df = 6, p.value = 0.0176

という正しい結果を返す。

ついでに,連続性の補正もできるようになっているので,

julia> G2_test(x, correct=true)
chisq. = 13.77649, df = 6, p.value = 0.03224

のようになる。

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村