distribution 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data.tar.gz.sig +0 -0
- data/.autotest +23 -0
- data/History.txt +3 -0
- data/Manifest.txt +39 -0
- data/README.txt +71 -0
- data/Rakefile +19 -0
- data/bin/distribution +3 -0
- data/lib/distribution.rb +148 -0
- data/lib/distribution/bivariatenormal.rb +25 -0
- data/lib/distribution/bivariatenormal/gsl.rb +11 -0
- data/lib/distribution/bivariatenormal/ruby.rb +281 -0
- data/lib/distribution/bivariatenormal/statistics2.rb +0 -0
- data/lib/distribution/chisquare.rb +29 -0
- data/lib/distribution/chisquare/gsl.rb +27 -0
- data/lib/distribution/chisquare/ruby.rb +85 -0
- data/lib/distribution/chisquare/statistics2.rb +21 -0
- data/lib/distribution/f.rb +28 -0
- data/lib/distribution/f/gsl.rb +28 -0
- data/lib/distribution/f/ruby.rb +117 -0
- data/lib/distribution/f/statistics2.rb +26 -0
- data/lib/distribution/math_extension.rb +72 -0
- data/lib/distribution/normal.rb +36 -0
- data/lib/distribution/normal/gsl.rb +24 -0
- data/lib/distribution/normal/ruby.rb +99 -0
- data/lib/distribution/normal/statistics2.rb +14 -0
- data/lib/distribution/normalmultivariate.rb +73 -0
- data/lib/distribution/t.rb +27 -0
- data/lib/distribution/t/gsl.rb +29 -0
- data/lib/distribution/t/ruby.rb +105 -0
- data/lib/distribution/t/statistics2.rb +28 -0
- data/spec/bivariatenormal_spec.rb +63 -0
- data/spec/chisquare_spec.rb +89 -0
- data/spec/distribution_spec.rb +19 -0
- data/spec/f_spec.rb +107 -0
- data/spec/normal_spec.rb +105 -0
- data/spec/shorthand_function.rb +6 -0
- data/spec/shorthand_spec.rb +14 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +23 -0
- data/spec/t_spec.rb +98 -0
- metadata +160 -0
- metadata.gz.sig +1 -0
File without changes
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'distribution/chisquare/ruby'
|
2
|
+
require 'distribution/chisquare/gsl'
|
3
|
+
require 'distribution/chisquare/statistics2'
|
4
|
+
module Distribution
|
5
|
+
# Calculate cdf and inverse cdf for Chi Square Distribution.
|
6
|
+
#
|
7
|
+
module ChiSquare
|
8
|
+
extend Distributable
|
9
|
+
SHORTHAND='chisq'
|
10
|
+
create_distribution_methods
|
11
|
+
|
12
|
+
##
|
13
|
+
# :singleton-method: pdf(x)
|
14
|
+
# Returns PDF of of Chi-squared distribution
|
15
|
+
# with +k+ degrees of freedom
|
16
|
+
|
17
|
+
|
18
|
+
##
|
19
|
+
# :singleton-method: cdf(x,k)
|
20
|
+
# Returns the integral of Chi-squared distribution
|
21
|
+
# with +k+ degrees of freedom over [0, +x+]
|
22
|
+
|
23
|
+
##
|
24
|
+
# :singleton-method: p_value(qn, k)
|
25
|
+
# Return the P-value of the corresponding integral +qn+ with
|
26
|
+
# +k+ degrees of freedom
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Distribution
|
2
|
+
module ChiSquare
|
3
|
+
module GSL_
|
4
|
+
class << self
|
5
|
+
def rng(k,seed=nil)
|
6
|
+
|
7
|
+
end
|
8
|
+
def pdf(x,k)
|
9
|
+
GSL::Ran::chisq_pdf(x,k)
|
10
|
+
end
|
11
|
+
# Return the P-value of the corresponding integral with
|
12
|
+
# k degrees of freedom
|
13
|
+
def p_value(pr,k)
|
14
|
+
GSL::Cdf::chisq_Pinv(pr,k)
|
15
|
+
end
|
16
|
+
# Chi-square cumulative distribution function (cdf).
|
17
|
+
#
|
18
|
+
# Returns the integral of Chi-squared distribution
|
19
|
+
# with k degrees of freedom over [0, x]
|
20
|
+
#
|
21
|
+
def cdf(x, k)
|
22
|
+
GSL::Cdf::chisq_P(x,k)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Distribution
|
2
|
+
module ChiSquare
|
3
|
+
module Ruby_
|
4
|
+
class << self
|
5
|
+
|
6
|
+
include Distribution::MathExtension
|
7
|
+
|
8
|
+
def pdf(x,n)
|
9
|
+
if n == 1
|
10
|
+
1.0/Math.sqrt(2 * Math::PI * x) * Math::E**(-x/2.0)
|
11
|
+
elsif n == 2
|
12
|
+
0.5 * Math::E**(-x/2.0)
|
13
|
+
else
|
14
|
+
n = n.to_f
|
15
|
+
n2 = n/2
|
16
|
+
x = x.to_f
|
17
|
+
1.0 / 2**n2 / gamma(n2) * x**(n2 - 1.0) * Math.exp(-x/2.0)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
# CDF Inverse over [x, \infty)
|
23
|
+
# Pr([x, \infty)) = y -> x
|
24
|
+
def pchi2(n, y)
|
25
|
+
if n == 1
|
26
|
+
|
27
|
+
w = Distribution::Normal.p_value(1 - y/2) # = p1.0-Distribution::Normal.cdf(y/2)
|
28
|
+
w * w
|
29
|
+
elsif n == 2
|
30
|
+
# v = (1.0 / y - 1.0) / 33.0
|
31
|
+
# newton_a(y, v) {|x| [q_chi2(n, x), -chi2dens(n, x)] }
|
32
|
+
-2.0 * Math.log(y)
|
33
|
+
else
|
34
|
+
eps = 1.0e-5
|
35
|
+
v = 0.0
|
36
|
+
s = 10.0
|
37
|
+
loop do
|
38
|
+
v += s
|
39
|
+
if s <= eps then break end
|
40
|
+
if (qe = q_chi2(n, v) - y) == 0.0 then break end
|
41
|
+
if qe < 0.0
|
42
|
+
v -= s
|
43
|
+
s /= 10.0 #/
|
44
|
+
end
|
45
|
+
end
|
46
|
+
v
|
47
|
+
end
|
48
|
+
end
|
49
|
+
def p_value(pr,k)
|
50
|
+
pchi2(k, 1.0-pr)
|
51
|
+
end
|
52
|
+
def cdf(x,k)
|
53
|
+
1.0-q_chi2(k,x)
|
54
|
+
end
|
55
|
+
|
56
|
+
# chi-square distribution ([1])
|
57
|
+
# Integral over [x, \infty)
|
58
|
+
def q_chi2(df, chi2)
|
59
|
+
chi2 = chi2.to_f
|
60
|
+
if (df & 1) != 0
|
61
|
+
chi = Math.sqrt(chi2)
|
62
|
+
if (df == 1) then return 2 * (1.0-Distribution::Normal.cdf(chi)); end
|
63
|
+
s = t = chi * Math.exp(-0.5 * chi2) / SQ2PI
|
64
|
+
k = 3
|
65
|
+
while k < df
|
66
|
+
t *= chi2 / k; s += t;
|
67
|
+
k += 2
|
68
|
+
end
|
69
|
+
2 * (1.0-(Distribution::Normal.cdf(chi)) + s)
|
70
|
+
else
|
71
|
+
s = t = Math.exp(-0.5 * chi2)
|
72
|
+
k = 2
|
73
|
+
while k < df
|
74
|
+
t *= chi2 / k; s += t;
|
75
|
+
k += 2
|
76
|
+
end
|
77
|
+
s
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Distribution
|
2
|
+
module ChiSquare
|
3
|
+
module Statistics2_
|
4
|
+
class << self
|
5
|
+
# Return the P-value of the corresponding integral with
|
6
|
+
# k degrees of freedom
|
7
|
+
def p_value(pr,k)
|
8
|
+
Statistics2.pchi2X_(k.to_i, pr)
|
9
|
+
end
|
10
|
+
# Chi-square cumulative distribution function (cdf).
|
11
|
+
#
|
12
|
+
# Returns the integral of Chi-squared distribution
|
13
|
+
# with k degrees of freedom over [0, x]
|
14
|
+
#
|
15
|
+
def cdf(x, k)
|
16
|
+
Statistics2.chi2dist(k.to_i,x)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'distribution/f/ruby'
|
2
|
+
require 'distribution/f/gsl'
|
3
|
+
require 'distribution/f/statistics2'
|
4
|
+
module Distribution
|
5
|
+
# Calculate cdf and inverse cdf for Chi Square Distribution.
|
6
|
+
#
|
7
|
+
module F
|
8
|
+
SHORTHAND='f'
|
9
|
+
extend Distributable
|
10
|
+
create_distribution_methods
|
11
|
+
|
12
|
+
##
|
13
|
+
# :singleton-method: pdf(x,k1,k2)
|
14
|
+
# Returns the PDF of F distribution
|
15
|
+
# with +k1+ and +k2+ degrees of freedom over [0, +x+]
|
16
|
+
|
17
|
+
##
|
18
|
+
# :singleton-method: p_value(qn, k1, k2)
|
19
|
+
# Return the P-value of the corresponding integral +qn+ with
|
20
|
+
# +k1+ and +k2+ degrees of freedom
|
21
|
+
|
22
|
+
##
|
23
|
+
# :singleton-method: cdf(x,k1,k2)
|
24
|
+
# Returns the integral of F distribution
|
25
|
+
# with +k1+ and +k2+ degrees of freedom over [0, +x+]
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Distribution
|
2
|
+
module F
|
3
|
+
module GSL_
|
4
|
+
class << self
|
5
|
+
def pdf(x,k1,k2)
|
6
|
+
GSL::Ran.fdist_pdf(x,k1,k2)
|
7
|
+
end
|
8
|
+
# Return the P-value of the corresponding integral with
|
9
|
+
# k degrees of freedom
|
10
|
+
#
|
11
|
+
# Distribution::F.p_value(0.95,1,2)
|
12
|
+
def p_value(pr,k1,k2)
|
13
|
+
GSL::Cdf.fdist_Pinv(pr,k1,k2)
|
14
|
+
end
|
15
|
+
# F cumulative distribution function (cdf).
|
16
|
+
#
|
17
|
+
# Returns the integral of F-distribution
|
18
|
+
# with k1 and k2 degrees of freedom
|
19
|
+
# over [0, x].
|
20
|
+
# Distribution::F.cdf(20,3,2)
|
21
|
+
#
|
22
|
+
def cdf(x, k1, k2)
|
23
|
+
GSL::Cdf.fdist_P(x.to_f,k1,k2)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module Distribution
|
2
|
+
module F
|
3
|
+
module Ruby_
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def c_pdf(f,df)
|
7
|
+
Distribution::ChiSquare.pdf(f,df)
|
8
|
+
end
|
9
|
+
def pdf(x,d1,d2)
|
10
|
+
Math.sqrt(((d1*x)**d1*(d2**d2)).quo((d1*x+d2)**(d1+d2))).quo( x*Math.beta(d1/2.0, d2/2.0))
|
11
|
+
end
|
12
|
+
# F-distribution ([1])
|
13
|
+
# Integral over [x, \infty)
|
14
|
+
def q_f(df1, df2, f)
|
15
|
+
if (f <= 0.0) then return 1.0; end
|
16
|
+
if (df1 % 2 != 0 && df2 % 2 == 0)
|
17
|
+
return 1.0 - q_f(df2, df1, 1.0 / f)
|
18
|
+
end
|
19
|
+
cos2 = 1.0 / (1.0 + df1.to_f * f / df2.to_f)
|
20
|
+
sin2 = 1.0 - cos2
|
21
|
+
|
22
|
+
if (df1 % 2 == 0)
|
23
|
+
prob = cos2 ** (df2.to_f / 2.0)
|
24
|
+
temp = prob
|
25
|
+
i = 2
|
26
|
+
while i < df1
|
27
|
+
temp *= (df2.to_f + i - 2) * sin2 / i
|
28
|
+
prob += temp
|
29
|
+
i += 2
|
30
|
+
end
|
31
|
+
return prob
|
32
|
+
end
|
33
|
+
prob = Math.atan(Math.sqrt(df2.to_f / (df1.to_f * f)))
|
34
|
+
temp = Math.sqrt(sin2 * cos2)
|
35
|
+
i = 3
|
36
|
+
while i <= df1
|
37
|
+
prob += temp
|
38
|
+
temp *= (i - 1).to_f * sin2 / i.to_f;
|
39
|
+
i += 2.0
|
40
|
+
end
|
41
|
+
temp *= df1.to_f
|
42
|
+
i = 3
|
43
|
+
while i <= df2
|
44
|
+
prob -= temp
|
45
|
+
temp *= (df1.to_f + i - 2) * cos2 / i.to_f
|
46
|
+
i += 2
|
47
|
+
end
|
48
|
+
prob * 2.0 / Math::PI
|
49
|
+
end
|
50
|
+
|
51
|
+
# inverse of F-distribution ([2])
|
52
|
+
def pfsub(x, y, z)
|
53
|
+
(Math.sqrt(z) - y) / x / 2.0
|
54
|
+
end
|
55
|
+
|
56
|
+
# Inverse CDF
|
57
|
+
# [x, \infty)
|
58
|
+
def pf(q, n1, n2)
|
59
|
+
if(q < 0.0 || q > 1.0 || n1 < 1 || n2 < 1)
|
60
|
+
$stderr.printf("Error : Illegal parameter in pf()!\n")
|
61
|
+
return 0.0
|
62
|
+
end
|
63
|
+
|
64
|
+
if n1 <= 240 || n2 <= 240
|
65
|
+
eps = 1.0e-5
|
66
|
+
if(n2 == 1) then eps = 1.0e-4 end
|
67
|
+
fw = 0.0
|
68
|
+
s = 1000.0
|
69
|
+
loop do
|
70
|
+
fw += s
|
71
|
+
if s <= eps then return fw end
|
72
|
+
if (qe = q_f(n1, n2, fw) - q) == 0.0 then return fw end
|
73
|
+
if qe < 0.0
|
74
|
+
fw -= s
|
75
|
+
s /= 10.0 #/
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
eps = 1.0e-6
|
81
|
+
qn = q
|
82
|
+
if q < 0.5 then qn = 1.0 - q
|
83
|
+
u = pnorm(qn)
|
84
|
+
w1 = 2.0 / n1 / 9.0
|
85
|
+
w2 = 2.0 / n2 / 9.0
|
86
|
+
w3 = 1.0 - w1
|
87
|
+
w4 = 1.0 - w2
|
88
|
+
u2 = u * u
|
89
|
+
a = w4 * w4 - u2 * w2
|
90
|
+
b = -2. * w3 * w4
|
91
|
+
c = w3 * w3 - u2 * w1
|
92
|
+
d = b * b - 4 * a * c
|
93
|
+
if(d < 0.0)
|
94
|
+
fw = pfsub(a, b, 0.0)
|
95
|
+
else
|
96
|
+
if(a.abs > eps)
|
97
|
+
fw = pfsub(a, b, d)
|
98
|
+
else
|
99
|
+
if(b.abs > eps) then return -c / b end
|
100
|
+
fw = pfsub(a, b, 0.0)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
fw * fw * fw
|
104
|
+
end
|
105
|
+
end
|
106
|
+
# F-distribution interface
|
107
|
+
def cdf(f,n1, n2)
|
108
|
+
1.0 - q_f(n1, n2, f)
|
109
|
+
end
|
110
|
+
def p_value(y, n1, n2)
|
111
|
+
pf(1.0 - y, n1, n2)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Distribution
|
2
|
+
module F
|
3
|
+
module Statistics2_
|
4
|
+
class << self
|
5
|
+
# Return the P-value of the corresponding integral with
|
6
|
+
# k degrees of freedom
|
7
|
+
#
|
8
|
+
# Distribution::F.p_value(0.95,1,2)
|
9
|
+
# Statistics2 have some problem with extreme values
|
10
|
+
def p_value(pr,k1,k2)
|
11
|
+
Statistics2.pfdist(k1,k2, pr)
|
12
|
+
end
|
13
|
+
# F cumulative distribution function (cdf).
|
14
|
+
#
|
15
|
+
# Returns the integral of F-distribution
|
16
|
+
# with k1 and k2 degrees of freedom
|
17
|
+
# over [0, x].
|
18
|
+
# Distribution::F.cdf(20,3,2)
|
19
|
+
#
|
20
|
+
def cdf(x, k1, k2)
|
21
|
+
Statistics2.fdist(k1, k2,x)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Useful additions to Math
|
2
|
+
module Distribution
|
3
|
+
module MathExtension
|
4
|
+
# Factorial for n
|
5
|
+
def factorial(n)
|
6
|
+
sum=1
|
7
|
+
2.upto(n) do |i|
|
8
|
+
sum*=n
|
9
|
+
end
|
10
|
+
sum
|
11
|
+
end
|
12
|
+
|
13
|
+
# Beta function.
|
14
|
+
# Source:
|
15
|
+
# * http://mathworld.wolfram.com/BetaFunction.html
|
16
|
+
def beta(x,y)
|
17
|
+
(gamma(x)*gamma(y)).quo(gamma(x+y))
|
18
|
+
end
|
19
|
+
|
20
|
+
LOG_2PI = Math.log(2 * Math::PI)# log(2PI)
|
21
|
+
N = 8
|
22
|
+
B0 = 1.0
|
23
|
+
B1 = -1.0 / 2.0
|
24
|
+
B2 = 1.0 / 6.0
|
25
|
+
B4 = -1.0 / 30.0
|
26
|
+
B6 = 1.0 / 42.0
|
27
|
+
B8 = -1.0 / 30.0
|
28
|
+
B10 = 5.0 / 66.0
|
29
|
+
B12 = -691.0 / 2730.0
|
30
|
+
B14 = 7.0 / 6.0
|
31
|
+
B16 = -3617.0 / 510.0
|
32
|
+
# From statistics2
|
33
|
+
def loggamma(x)
|
34
|
+
v = 1.0
|
35
|
+
while (x < N)
|
36
|
+
v *= x
|
37
|
+
x += 1.0
|
38
|
+
end
|
39
|
+
w = 1.0 / (x * x)
|
40
|
+
ret = B16 / (16 * 15)
|
41
|
+
ret = ret * w + B14 / (14 * 13)
|
42
|
+
ret = ret * w + B12 / (12 * 11)
|
43
|
+
ret = ret * w + B10 / (10 * 9)
|
44
|
+
ret = ret * w + B8 / ( 8 * 7)
|
45
|
+
ret = ret * w + B6 / ( 6 * 5)
|
46
|
+
ret = ret * w + B4 / ( 4 * 3)
|
47
|
+
ret = ret * w + B2 / ( 2 * 1)
|
48
|
+
ret = ret / x + 0.5 * LOG_2PI - Math.log(v) - x + (x - 0.5) * Math.log(x)
|
49
|
+
ret
|
50
|
+
end
|
51
|
+
# Gamma function.
|
52
|
+
# From statistics2
|
53
|
+
def gamma(x)
|
54
|
+
if (x < 0.0)
|
55
|
+
return Math::PI / (Math.sin(Math.PI * x) * Math.exp(loggamma(1 - x))) #/
|
56
|
+
end
|
57
|
+
Math.exp(loggamma(x))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
module Math
|
63
|
+
include Distribution::MathExtension
|
64
|
+
module_function :factorial, :beta, :gamma
|
65
|
+
end
|
66
|
+
|
67
|
+
# Necessary on Ruby 1.9
|
68
|
+
module CMath # :nodoc:
|
69
|
+
include Distribution::MathExtension
|
70
|
+
module_function :factorial, :beta, :gamma
|
71
|
+
end
|
72
|
+
|