#==========
Julia の修行をするときに,いろいろなプログラムを書き換えるのは有効な方法だ。
以下のプログラムを Julia に翻訳してみる。
2×2 分割表のフィッシャーの正確確率検定
http://aoki2.si.gunma-u.ac.jp/R/my-fisher.html
ファイル名: myfisher.jl
関数名: myfisher(x::Array{Int64, 2})
myfisher(a::Int64, b::Int64, c::Int64, d::Int64)
翻訳するときに書いたメモ
同じ名前で 2 個の関数を定義。
==========#
using SpecialFunctions, Printf
function myfisher(x::Array{Int64, 2})
myfisher(x[1,1], x[1,2], x[2,1], x[2,2])
end
function myfisher(a::Int64, b::Int64, c::Int64, d::Int64)
mark(i) = i == 1 ? "@" : " "
ct = [a + c, b + d]
rt = [a + b, c + d]
n = sum(ct)
mx = min(rt[1], ct[1])
mi = max(0, rt[1]+ct[1]-n)
A = mi:mx
B = rt[1] .- A
C = ct[1] .- A
D = ct[2] .- B
nrow = length(A)
Chisq = zeros(nrow);
OddsRatio = similar(Chisq);
Probability = similar(Chisq);
for i = 1:nrow
Chisq[i], OddsRatio[i], Probability[i] = stats(A[i], B[i], C[i], D[i])
end
CumProb1 = cumsum(Probability);
CumProb2 = reverse(cumsum(reverse(Probability)));
Chisq0, OddsRatio0, Probability0 = stats(a, b, c, d)
Pearson = Chisq .>= Chisq0 - 1e-15
Fisher = Probability .<= Probability0 + 1e-15
OR = OddsRatio .>= OddsRatio0 - 1e-15
pPearson = sum(Probability[Pearson])
pFisher = sum(Probability[Fisher])
pOR = sum(Probability[OR])
println(" ピアソンの基準による p 値 = $pPearson")
println("フィッシャーの基準による p 値 = $pFisher")
println(" オッズ比を基準とした p 値 = $pOR")
@printf("%3s %3s %3s %3s %8s %12s %10s %10s %1s%1s%1s %9s\n",
"A", "B", "C", "D", "Chi.sq", "Probability", "OddsRatio",
"Cum.Prob1", "P", "F", "O", "Cum.Prob2")
for i = 1:nrow
@printf("%3d %3d %3d %3d %8.3f %12.9f %10.3f %10.7f %1s%1s%1s %9.7f\n",
A[i], B[i], C[i], D[i], Chisq[i], Probability[i], OddsRatio[i],
CumProb1[i], mark(Pearson[i]), mark(Fisher[i]), mark(OR[i]), CumProb2[i])
end
Dict(:pPearson => pPearson, :pFisher => pFisher, :pOR => pOR)
end
function oddsratio(a, b, c, d)
if a*b*c*d == 0
a, b, c, d = a + 0.5, b + 0.5, c + 0.5, d + 0.5
end
res = a * d / (b * c)
max(res, 1 / res)
end
lchoose(n, x) = logfactorial(n) - logfactorial(x) - logfactorial(n - x)
function stats(a, b, c, d)
e, f, g, h = a + b, c + d, a + c, b + d
n = e + f
n * (a * d - b * c)^2 / (e * f * g * h), oddsratio(a, b, c, d),
exp(lchoose(e, a) + lchoose(f, c) - lchoose(n, g))
end
myfisher([10 13; 16 61])
myfisher(10, 13, 16, 61)
# ピアソンの基準による p 値 = 0.03529413313496242
# フィッシャーの基準による p 値 = 0.05508990606358157
# オッズ比を基準とした p 値 = 0.05508990606358157
# A B C D Chi.sq Probability OddsRatio Cum.Prob1 PFO Cum.Prob2
# 0 23 26 51 10.495 0.000331755 24.184 0.0003318 @@@ 1.0000000
# 1 22 25 52 7.278 0.003815185 10.577 0.0041469 @@@ 0.9996682
# 2 21 24 53 4.649 0.019795773 4.755 0.0239427 @@ 0.9958531
# 3 20 23 54 2.606 0.061586849 2.840 0.0855296 0.9760573
# 4 19 22 55 1.151 0.128772503 1.900 0.2143021 0.9144704
# 5 18 21 56 0.282 0.192238950 1.350 0.4065410 0.7856979
# 6 17 20 57 0.000 0.212474629 1.006 0.6190156 0.5934590
# 7 16 19 58 0.305 0.177934419 1.336 0.7969501 0.3809844
# 8 15 18 59 1.198 0.114601829 1.748 0.9115519 0.2030499
# 9 14 17 60 2.677 0.057300915 2.269 0.9688528 0.0884481
# 10 13 16 61 4.743 0.022356750 2.933 0.9912096 @@@ 0.0311472
# 11 12 15 62 7.396 0.006818481 3.789 0.9980280 @@@ 0.0087904
# 12 11 14 63 10.636 0.001623448 4.909 0.9996515 @@@ 0.0019720
# 13 10 13 64 14.463 0.000300494 6.400 0.9999520 @@@ 0.0003485
# 14 9 12 65 18.877 0.000042928 8.426 0.9999949 @@@ 0.0000480
# 15 8 11 66 23.878 0.000004683 11.250 0.9999996 @@@ 0.0000051
# 16 7 10 67 29.465 0.000000384 15.314 1.0000000 @@@ 0.0000004
# 17 6 9 68 35.640 0.000000023 21.407 1.0000000 @@@ 0.0000000
# 18 5 8 69 42.402 0.000000001 31.050 1.0000000 @@@ 0.0000000
# 19 4 7 70 49.751 0.000000000 47.500 1.0000000 @@@ 0.0000000
# 20 3 6 71 57.686 0.000000000 78.889 1.0000000 @@@ 0.0000000
# 21 2 5 72 66.209 0.000000000 151.200 1.0000000 @@@ 0.0000000
# 22 1 4 73 75.318 0.000000000 401.500 1.0000000 @@@ 0.0000000
# 23 0 3 74 85.015 0.000000000 1000.429 1.0000000 @@@ 0.0000000
# Dict{Symbol,Float64} with 3 entries:
# :pOR => 0.0550899
# :pPearson => 0.0352941
# :pFisher => 0.0550899