rubystats 0.2.3 → 0.4.1
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.
- checksums.yaml +7 -0
- data/.github/workflows/test.yml +21 -0
- data/.gitignore +20 -0
- data/Gemfile +3 -0
- data/History.txt +34 -0
- data/{README.txt → README.rdoc} +18 -7
- data/Rakefile +11 -44
- data/examples/uniform.rb +14 -0
- data/lib/rubystats/beta_distribution.rb +4 -0
- data/lib/rubystats/binomial_distribution.rb +42 -131
- data/lib/rubystats/cauchy_distribution.rb +50 -0
- data/lib/rubystats/exponential_distribution.rb +2 -2
- data/lib/rubystats/fishers_exact_test.rb +9 -9
- data/lib/rubystats/gamma_distribution.rb +70 -0
- data/lib/rubystats/lognormal_distribution.rb +59 -0
- data/lib/rubystats/modules.rb +57 -48
- data/lib/rubystats/multivariate_normal_distribution.rb +73 -0
- data/lib/rubystats/normal_distribution.rb +4 -3
- data/lib/rubystats/poisson_distribution.rb +78 -0
- data/lib/rubystats/probability_distribution.rb +4 -4
- data/lib/rubystats/student_t_distribution.rb +62 -0
- data/lib/rubystats/uniform_distribution.rb +70 -0
- data/lib/rubystats/version.rb +3 -0
- data/lib/rubystats/weibull_distribution.rb +56 -0
- data/lib/rubystats.rb +39 -5
- data/rubystats.gemspec +28 -0
- data/test/tc_beta.rb +90 -69
- data/test/tc_binomial.rb +30 -16
- data/test/tc_cauchy.rb +39 -0
- data/test/tc_exponential.rb +13 -3
- data/test/tc_fisher.rb +15 -15
- data/test/tc_gamma.rb +39 -0
- data/test/tc_lnorm.rb +45 -0
- data/test/tc_multivariate_normal.rb +53 -0
- data/test/tc_norm.rb +35 -6
- data/test/tc_poisson.rb +35 -0
- data/test/tc_require_all.rb +5 -5
- data/test/tc_studentt.rb +43 -0
- data/test/tc_unif.rb +48 -0
- data/test/tc_weibull.rb +51 -0
- data/test/ts_stats.rb +1 -1
- metadata +115 -47
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubystats/probability_distribution'
|
2
|
+
module Rubystats
|
3
|
+
class WeibullDistribution < Rubystats::ProbabilityDistribution
|
4
|
+
include Rubystats::NumericalConstants
|
5
|
+
|
6
|
+
def initialize(scale=1.0, shape=1.0)
|
7
|
+
if scale <= 0.0
|
8
|
+
raise ArgumentError.new("Scale parameter should be greater than zero.")
|
9
|
+
end
|
10
|
+
if shape <= 0.0
|
11
|
+
raise ArgumentError.new("Shape parameter should be greater than zero.")
|
12
|
+
end
|
13
|
+
@scale = scale.to_f
|
14
|
+
@shape = shape.to_f
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def get_mean
|
20
|
+
@scale * Math.gamma(1.0 + 1.0 / @shape)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_variance
|
24
|
+
@scale**2 * (Math.gamma(1.0 + 2.0 / @shape) - (Math.gamma(1.0 + 1.0 / @shape))**2)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Private method to obtain single PDF value.
|
28
|
+
# x should be greater than or equal to 0.0
|
29
|
+
# returns the probability that a stochastic variable x has the value X, i.e. P(x=X).
|
30
|
+
def get_pdf(x)
|
31
|
+
check_range(x, 0.0, MAX_VALUE)
|
32
|
+
(@shape / @scale) * (x / @scale)**(@shape-1.0) * Math.exp(-1.0 * ((x/@scale)**@shape))
|
33
|
+
end
|
34
|
+
|
35
|
+
# Private method to obtain single CDF value.
|
36
|
+
# param x should be greater than 0
|
37
|
+
# return the probability that a stochastic variable x is less then X, i.e. P(x<X).
|
38
|
+
def get_cdf(x)
|
39
|
+
check_range(x,0.0,MAX_VALUE)
|
40
|
+
1.0 - Math.exp(-1.0 * ((x.to_f/@scale)**@shape))
|
41
|
+
end
|
42
|
+
|
43
|
+
# Private method to obtain single inverse CDF value.
|
44
|
+
# return the value X for which P(x<X).
|
45
|
+
def get_icdf(p)
|
46
|
+
check_range(p)
|
47
|
+
@scale * (-1.0 * Math.log(1.0 - p.to_f))**(1.0 / @shape)
|
48
|
+
end
|
49
|
+
|
50
|
+
# Private method to obtain single RNG value.
|
51
|
+
def get_rng
|
52
|
+
self.icdf(Kernel.rand)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
data/lib/rubystats.rb
CHANGED
@@ -1,10 +1,44 @@
|
|
1
|
-
module Rubystats
|
2
|
-
VERSION = '0.2.3'
|
3
|
-
end
|
4
|
-
|
5
1
|
require 'rubystats/normal_distribution'
|
6
2
|
require 'rubystats/binomial_distribution'
|
3
|
+
require 'rubystats/poisson_distribution'
|
7
4
|
require 'rubystats/beta_distribution'
|
8
5
|
require 'rubystats/fishers_exact_test'
|
9
6
|
require 'rubystats/exponential_distribution'
|
10
|
-
|
7
|
+
require 'rubystats/uniform_distribution'
|
8
|
+
require 'rubystats/lognormal_distribution'
|
9
|
+
require 'rubystats/student_t_distribution'
|
10
|
+
require 'rubystats/weibull_distribution'
|
11
|
+
require 'rubystats/cauchy_distribution'
|
12
|
+
require 'rubystats/gamma_distribution'
|
13
|
+
require 'rubystats/multivariate_normal_distribution'
|
14
|
+
require 'rubystats/version'
|
15
|
+
|
16
|
+
module Rubystats
|
17
|
+
end
|
18
|
+
|
19
|
+
NormalDistribution = Rubystats::NormalDistribution
|
20
|
+
BinomialDistribution = Rubystats::BinomialDistribution
|
21
|
+
PoissonDistribution = Rubystats::PoissonDistribution
|
22
|
+
BetaDistribution = Rubystats::BetaDistribution
|
23
|
+
FishersExactTest = Rubystats::FishersExactTest
|
24
|
+
ExponentialDistribution = Rubystats::ExponentialDistribution
|
25
|
+
UniformDistribution = Rubystats::UniformDistribution
|
26
|
+
LognormalDistribution = Rubystats::LognormalDistribution
|
27
|
+
StudentTDistribution = Rubystats::StudentTDistribution
|
28
|
+
WeibullDistribution = Rubystats::WeibullDistribution
|
29
|
+
CauchyDistribution = Rubystats::CauchyDistribution
|
30
|
+
GammaDistribution = Rubystats::GammaDistribution
|
31
|
+
MultivariateNormalDistribution = Rubystats::MultivariateNormalDistribution
|
32
|
+
|
33
|
+
#short-hand notation
|
34
|
+
Normal = Rubystats::NormalDistribution
|
35
|
+
Binomial = Rubystats::BinomialDistribution
|
36
|
+
Poisson = Rubystats::PoissonDistribution
|
37
|
+
Beta = Rubystats::BetaDistribution
|
38
|
+
Exponential = Rubystats::ExponentialDistribution
|
39
|
+
Uniform = Rubystats::UniformDistribution
|
40
|
+
Lognormal = Rubystats::LognormalDistribution
|
41
|
+
Weibull = Rubystats::WeibullDistribution
|
42
|
+
Cauchy = Rubystats::CauchyDistribution
|
43
|
+
Gamma = Rubystats::GammaDistribution
|
44
|
+
MultivariateNormal = Rubystats::MultivariateNormalDistribution
|
data/rubystats.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path("../lib", __FILE__)
|
2
|
+
require 'rubystats/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = 'rubystats'
|
6
|
+
s.version = Rubystats::VERSION
|
7
|
+
s.license = "MIT"
|
8
|
+
s.summary = ''
|
9
|
+
s.description = "Ruby Stats is a port of the statistics libraries from PHPMath. Probability distributions include binomial, beta, and normal distributions with PDF, CDF and inverse CDF as well as Fisher's Exact Test."
|
10
|
+
|
11
|
+
s.files = `git ls-files`.split("\n")
|
12
|
+
s.test_files = `git ls-files -- Appraisals {test,spec,features,gemfiles}/*`.split("\n")
|
13
|
+
|
14
|
+
s.require_paths = ['lib']
|
15
|
+
s.required_ruby_version = Gem::Requirement.new(">= 1.9.3")
|
16
|
+
|
17
|
+
s.authors = ['Ilya Scharrenbroich', 'Bryan Donovan - http://www.bryandonovan.com', 'Phillip Baker']
|
18
|
+
|
19
|
+
s.homepage = 'https://github.com/phillbaker/rubystats'
|
20
|
+
|
21
|
+
s.add_development_dependency("minitest", ">= 4.2", "< 5.0")
|
22
|
+
s.add_development_dependency("hoe", ">= 1.7.0")
|
23
|
+
|
24
|
+
# matrix was removed from default gems in Ruby 3.1, see
|
25
|
+
# https://github.com/ruby/ruby/pull/4530 and https://stdgems.org/
|
26
|
+
s.add_runtime_dependency("matrix")
|
27
|
+
end
|
28
|
+
|
data/test/tc_beta.rb
CHANGED
@@ -1,51 +1,51 @@
|
|
1
1
|
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
-
require '
|
2
|
+
require 'minitest/autorun'
|
3
3
|
require 'rubystats/beta_distribution'
|
4
4
|
|
5
|
-
class TestBeta <
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
class TestBeta < MiniTest::Unit::TestCase
|
6
|
+
def test_simple
|
7
|
+
p = 12
|
8
|
+
q = 59
|
9
|
+
beta = Rubystats::BetaDistribution.new(p,q)
|
10
|
+
assert_equal("0.16901408450704225", beta.mean.to_s)
|
11
|
+
assert_equal("0.04416640310381873", beta.standard_deviation.to_s)
|
12
|
+
assert_equal("6.260758158499666", beta.pdf(0.2).to_s)
|
13
|
+
assert_equal("0.9999999977669126", beta.cdf(0.50).to_s)
|
14
|
+
assert_equal("0.10200319411356515", beta.icdf(0.05).to_s)
|
15
|
+
|
16
|
+
x_vals = [0.1, 0.15, 0.2, 0.25, 0.3, 0.35]
|
17
|
+
p_vals = beta.pdf(x_vals)
|
18
|
+
c_vals = beta.cdf(x_vals)
|
19
|
+
expected_pvals = [ 2.83232625227534,
|
20
|
+
8.89978000366836,
|
21
|
+
6.26075815849967,
|
22
|
+
1.72572305993386,
|
23
|
+
0.234475706454223,
|
24
|
+
0.0173700433944934]
|
25
|
+
expected_cvals = [0.0440640755091473,
|
26
|
+
0.356009606171447,
|
27
|
+
0.768319101921981,
|
28
|
+
0.956058132801147,
|
29
|
+
0.995358286711105,
|
30
|
+
0.99971672771575]
|
15
31
|
|
16
|
-
x_vals = [0.1, 0.15, 0.2, 0.25, 0.3, 0.35]
|
17
|
-
p_vals = beta.pdf(x_vals)
|
18
|
-
c_vals = beta.cdf(x_vals)
|
19
|
-
expected_pvals = [ 2.83232625227534,
|
20
|
-
8.89978000366836,
|
21
|
-
6.26075815849967,
|
22
|
-
1.72572305993386,
|
23
|
-
0.234475706454223,
|
24
|
-
0.0173700433944934]
|
25
|
-
expected_cvals = [0.0440640755091473,
|
26
|
-
0.356009606171447,
|
27
|
-
0.768319101921981,
|
28
|
-
0.956058132801147,
|
29
|
-
0.995358286711105,
|
30
|
-
0.99971672771575]
|
31
|
-
|
32
32
|
0.upto(x_vals.size - 1) do |i|
|
33
33
|
assert_in_delta expected_pvals[i], p_vals[i], 0.00000001
|
34
34
|
assert_in_delta expected_cvals[i], c_vals[i], 0.00000001
|
35
35
|
i += 1
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
x_vals.each do |x|
|
39
|
+
cdf = beta.cdf(x)
|
40
|
+
inv_cdf = beta.icdf(cdf)
|
41
|
+
assert_in_delta(x, inv_cdf, 0.00000001)
|
42
|
+
end
|
43
|
+
end
|
44
44
|
|
45
45
|
def test_low_p_and_q_values
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
p = 1.5
|
47
|
+
q = 1.0
|
48
|
+
beta = Rubystats::BetaDistribution.new(p,q)
|
49
49
|
|
50
50
|
#from PHPExcel/PHPMath output
|
51
51
|
expected_icdf_vals = [
|
@@ -60,41 +60,62 @@ class TestBeta < Test::Unit::TestCase
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
63
|
+
def test_control_limits
|
64
|
+
trials = 50
|
65
|
+
alpha = 0.05
|
66
|
+
p = 10
|
67
|
+
lcl = get_lower_limit(trials, alpha, p)
|
68
|
+
ucl = get_upper_limit(trials, alpha, p)
|
69
|
+
assert_equal("0.1127216134140763",lcl.to_s)
|
70
|
+
assert_equal("0.3155960614200132",ucl.to_s)
|
71
|
+
|
72
|
+
trials = 210
|
73
|
+
alpha = 0.10
|
74
|
+
p = 47
|
75
|
+
lcl = get_lower_limit(trials, alpha, p)
|
76
|
+
ucl = get_upper_limit(trials, alpha, p)
|
77
|
+
assert_equal("0.18667948526990116",lcl.to_s)
|
78
|
+
assert_equal("0.2649576017835441",ucl.to_s)
|
79
|
+
end
|
71
80
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
81
|
+
def get_lower_limit(trials,alpha,p)
|
82
|
+
if p==0
|
83
|
+
lcl=0
|
84
|
+
else
|
85
|
+
q=trials-p+1
|
86
|
+
bin= Rubystats::BetaDistribution.new(p,q)
|
87
|
+
lcl=bin.icdf(alpha)
|
88
|
+
end
|
89
|
+
return lcl
|
90
|
+
end
|
80
91
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
92
|
+
def get_upper_limit(trials,alpha,p)
|
93
|
+
q=trials-p
|
94
|
+
p=p+1
|
95
|
+
bin= Rubystats::BetaDistribution.new(p,q)
|
96
|
+
ucl=bin.icdf(1-alpha)
|
97
|
+
return ucl
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_rng_distribution
|
101
|
+
p = 4.0
|
102
|
+
q = 12.0
|
103
|
+
beta = Rubystats::BetaDistribution.new(p,q)
|
104
|
+
|
105
|
+
total = 10000
|
106
|
+
values = Array.new(total).map{ beta.rng }
|
91
107
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
bin= Rubystats::BetaDistribution.new(p,q)
|
96
|
-
ucl=bin.icdf(1-alpha)
|
97
|
-
return ucl
|
98
|
-
end
|
108
|
+
mean = values.inject(0.0) {|sum,v| sum + v} / values.size
|
109
|
+
assert_in_epsilon 0.25, mean.round(2), 0.01
|
110
|
+
end
|
99
111
|
|
112
|
+
def test_integer_input
|
113
|
+
pi, qi = 2, 4
|
114
|
+
pf, qf = 2.0, 4.0
|
115
|
+
x = 0.25
|
116
|
+
dbetai = Rubystats::BetaDistribution.new(pi,qi).pdf(x)
|
117
|
+
dbetaf = Rubystats::BetaDistribution.new(pf,qf).pdf(x)
|
118
|
+
assert_in_delta dbetai, dbetaf, 0.00000001
|
119
|
+
end
|
120
|
+
|
100
121
|
end
|
data/test/tc_binomial.rb
CHANGED
@@ -1,22 +1,36 @@
|
|
1
1
|
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
-
require '
|
2
|
+
require 'minitest/autorun'
|
3
3
|
require 'rubystats/binomial_distribution'
|
4
4
|
|
5
|
-
class TestBinomial <
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
class TestBinomial < MiniTest::Unit::TestCase
|
6
|
+
def test_simple
|
7
|
+
t = 100
|
8
|
+
f = 7
|
9
|
+
p = 0.05
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
bin = Rubystats::BinomialDistribution.new(t,p)
|
12
|
+
cdf = bin.cdf(f)
|
13
|
+
pmf = bin.pmf(f)
|
14
|
+
pdf = bin.pdf(f)
|
15
|
+
mean = bin.mean
|
16
|
+
inv_cdf = bin.icdf(cdf)
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
assert_equal pmf, pdf
|
19
|
+
assert_in_delta(0.10602553736479, pdf, 0.00000000000001 )
|
20
|
+
assert_in_delta(0.87203952137960, cdf, 0.00000000000001)
|
21
|
+
assert_equal("5.0",mean.to_s)
|
22
|
+
assert_equal(f,inv_cdf)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_rng
|
26
|
+
t, p = 100, 0.75
|
27
|
+
bin = Rubystats::BinomialDistribution.new(t,p)
|
28
|
+
|
29
|
+
rngs = []
|
30
|
+
n = 1000
|
31
|
+
n.times { rngs << bin.rng.to_f }
|
32
|
+
avg = rngs.reduce(:+) / rngs.size
|
33
|
+
|
34
|
+
assert_in_delta(avg, bin.mean, 0.5)
|
35
|
+
end
|
22
36
|
end
|
data/test/tc_cauchy.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'rubystats/cauchy_distribution'
|
4
|
+
|
5
|
+
class TestCauchy < MiniTest::Unit::TestCase
|
6
|
+
def test_simple
|
7
|
+
location = 0.0
|
8
|
+
scale = 0.5
|
9
|
+
cd = Rubystats::CauchyDistribution.new(location,scale)
|
10
|
+
assert_in_delta(0.6366198, cd.pdf(0.0), 0.000001)
|
11
|
+
assert_in_delta(0.5, cd.cdf(0.0), 0.00000001)
|
12
|
+
assert_in_delta(3.169765, cd.icdf(0.9502), 0.000001)
|
13
|
+
|
14
|
+
# make sure the mean of RNG values is close to the expected mean
|
15
|
+
rngs = []
|
16
|
+
n = 10000
|
17
|
+
n.times {|i| rngs << cd.rng }
|
18
|
+
quantile = rngs.sort[(0.75*rngs.size).ceil]
|
19
|
+
assert_in_delta(quantile, 0.5, 0.1)
|
20
|
+
|
21
|
+
x_vals = [-2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0]
|
22
|
+
|
23
|
+
x_vals.each do |x|
|
24
|
+
cdf = cd.cdf(x)
|
25
|
+
inv_cdf = cd.icdf(cdf)
|
26
|
+
assert_in_delta(x, inv_cdf, 0.00000001)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_integer_input
|
31
|
+
locationi, scalei = 3, 1
|
32
|
+
locationf, scalef = 3.0, 1.0
|
33
|
+
xi = 4
|
34
|
+
xf = 4.0
|
35
|
+
dcdi = Rubystats::CauchyDistribution.new(locationi,scalei).pdf(xi)
|
36
|
+
dcdf = Rubystats::CauchyDistribution.new(locationf,scalef).pdf(xf)
|
37
|
+
assert_in_delta dcdi, dcdf, 0.00000001
|
38
|
+
end
|
39
|
+
end
|
data/test/tc_exponential.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
-
require '
|
2
|
+
require 'minitest/autorun'
|
3
3
|
require 'rubystats/exponential_distribution'
|
4
4
|
|
5
|
-
class TestExponential <
|
5
|
+
class TestExponential < MiniTest::Unit::TestCase
|
6
6
|
def test_simple
|
7
7
|
lmbda = 1
|
8
8
|
expd = Rubystats::ExponentialDistribution.new(lmbda)
|
@@ -16,7 +16,7 @@ class TestExponential < Test::Unit::TestCase
|
|
16
16
|
rngs = []
|
17
17
|
rngsum = 0
|
18
18
|
n = 5000
|
19
|
-
n.times do
|
19
|
+
n.times do
|
20
20
|
rng = expd.rng
|
21
21
|
rngs << rng
|
22
22
|
rngsum += rng
|
@@ -57,4 +57,14 @@ class TestExponential < Test::Unit::TestCase
|
|
57
57
|
assert_in_delta(x, inv_cdf, 0.00000001)
|
58
58
|
end
|
59
59
|
end
|
60
|
+
|
61
|
+
def test_integer_input
|
62
|
+
lambdai = 2
|
63
|
+
lambdaf = 2.0
|
64
|
+
xi = 3
|
65
|
+
xf = 3.0
|
66
|
+
dexpi = Rubystats::ExponentialDistribution.new(lambdai).pdf(xi)
|
67
|
+
dexpf = Rubystats::ExponentialDistribution.new(lambdaf).pdf(xf)
|
68
|
+
assert_in_delta dexpi, dexpf, 0.00000001
|
69
|
+
end
|
60
70
|
end
|
data/test/tc_fisher.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
-
require '
|
2
|
+
require 'minitest/autorun'
|
3
3
|
require 'rubystats/fishers_exact_test'
|
4
4
|
|
5
|
-
class TestFisher <
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
class TestFisher < MiniTest::Unit::TestCase
|
6
|
+
def test_simple
|
7
|
+
tested1 = 20
|
8
|
+
tested2 = 30
|
9
|
+
f1 = 10
|
10
|
+
f2 = 10
|
11
|
+
t1 = tested1 - f1
|
12
|
+
t2 = tested2 - f2
|
13
|
+
fet = Rubystats::FishersExactTest.new
|
14
|
+
fisher = fet.calculate(t1,t2,f1,f2)
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
assert_equal("0.18830137576992229",fisher[:left].to_s)
|
17
|
+
assert_equal("0.9294811316610517",fisher[:right].to_s)
|
18
|
+
assert_equal("0.2575492428109919",fisher[:twotail].to_s)
|
19
|
+
end
|
20
20
|
end
|
data/test/tc_gamma.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'rubystats/gamma_distribution'
|
4
|
+
|
5
|
+
class TestGamma < MiniTest::Unit::TestCase
|
6
|
+
def test_simple
|
7
|
+
shape = 3.0
|
8
|
+
scale = 2.0
|
9
|
+
gamma = Rubystats::GammaDistribution.new(shape,scale)
|
10
|
+
|
11
|
+
#check properties
|
12
|
+
assert_in_delta(6.0, gamma.mean, 0.000001)
|
13
|
+
assert_in_delta(12.0, gamma.variance, 0.000001)
|
14
|
+
|
15
|
+
#check distributions
|
16
|
+
assert_in_delta(0.0, gamma.pdf(0.0), 0.000001)
|
17
|
+
assert_in_delta(0.1353353, gamma.pdf(4.0), 0.000001)
|
18
|
+
assert_in_delta(0.001134998, gamma.pdf(20.0), 0.000001)
|
19
|
+
assert_in_delta(0.5768099, gamma.cdf(6.0), 0.01)
|
20
|
+
assert_in_delta(0.986246, gamma.cdf(16.0), 0.01)
|
21
|
+
|
22
|
+
# make sure the mean of RNG values is close to the expected mean
|
23
|
+
rngs = []
|
24
|
+
n = 10000
|
25
|
+
n.times {|i| rngs << gamma.rng }
|
26
|
+
quantile = rngs.sort[(0.75*rngs.size).ceil]
|
27
|
+
assert_in_delta(quantile, 7.84080, 0.2)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_integer_input
|
31
|
+
shapei, scalei = 3, 1
|
32
|
+
shapef, scalef = 3.0, 1.0
|
33
|
+
xi = 4
|
34
|
+
xf = 4.0
|
35
|
+
pdfi = Rubystats::GammaDistribution.new(shapei,scalei).pdf(xi)
|
36
|
+
pdff = Rubystats::GammaDistribution.new(shapef,scalef).pdf(xf)
|
37
|
+
assert_in_delta pdfi, pdff, 0.00000001
|
38
|
+
end
|
39
|
+
end
|
data/test/tc_lnorm.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'rubystats/lognormal_distribution'
|
4
|
+
|
5
|
+
class TestLognormal < MiniTest::Unit::TestCase
|
6
|
+
def test_cdf_pdf
|
7
|
+
lnorm = Rubystats::LognormalDistribution.new(2.0,0.2)
|
8
|
+
|
9
|
+
cdf = lnorm.cdf(8.0)
|
10
|
+
assert_in_epsilon cdf, 0.654392, 0.0001, "cdf"
|
11
|
+
|
12
|
+
pdf = lnorm.pdf(8.0)
|
13
|
+
assert_in_epsilon pdf, 0.2304252, 0.000001, "pdf"
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_properties
|
18
|
+
lnorm = Rubystats::LognormalDistribution.new(2.0,0.2)
|
19
|
+
assert_in_epsilon lnorm.mean, 7.538325, 0.000001, "mean"
|
20
|
+
assert_in_epsilon lnorm.variance, 2.319127, 0.000001, "variance"
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_rng
|
24
|
+
lnorm = Rubystats::LognormalDistribution.new(2.0,0.2)
|
25
|
+
|
26
|
+
total = 100000
|
27
|
+
values = Array.new(total).map{lnorm.rng}
|
28
|
+
|
29
|
+
mean = values.inject(0.0) {|sum, v| sum + v} / values.size
|
30
|
+
|
31
|
+
assert_in_delta mean, 7.538325, 0.1, "rng mean"
|
32
|
+
assert_equal values.min >= 0.0, true, "rng min value"
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_integer_input
|
36
|
+
meani, sdi = 2, 1
|
37
|
+
meanf, sdf = 2.0, 1.0
|
38
|
+
xi = 9
|
39
|
+
xf = 9.0
|
40
|
+
dlnormi = Rubystats::LognormalDistribution.new(meani,sdi).pdf(xi)
|
41
|
+
dlnormf = Rubystats::LognormalDistribution.new(meanf,sdf).pdf(xf)
|
42
|
+
assert_in_delta dlnormi, dlnormf, 0.000001
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
2
|
+
require 'minitest/autorun'
|
3
|
+
require 'rubystats/multivariate_normal_distribution'
|
4
|
+
|
5
|
+
class TestMultivariateNormal < MiniTest::Unit::TestCase
|
6
|
+
def test_simple
|
7
|
+
mu = [1.3,-2.5]
|
8
|
+
sigma = [[1.0,0.3],[0.3,1.0]]
|
9
|
+
|
10
|
+
mvnorm = Rubystats::MultivariateNormalDistribution.new(mu,sigma)
|
11
|
+
|
12
|
+
assert_in_delta(0.0001340771, mvnorm.pdf([1.0,1.0]), 0.000001)
|
13
|
+
assert_in_delta(0.131732, mvnorm.pdf([1.0,-2.0]), 0.000001)
|
14
|
+
|
15
|
+
|
16
|
+
# make sure the mean of RNG values is close to the expected mean
|
17
|
+
rngs = []
|
18
|
+
n = 5000
|
19
|
+
n.times {|i| rngs << mvnorm.rng }
|
20
|
+
|
21
|
+
a,b = rngs.transpose
|
22
|
+
|
23
|
+
#check means
|
24
|
+
mean_a = a.inject(0.0) {|sum,x| sum + x} / a.size
|
25
|
+
assert_in_delta(1.3, mean_a, 0.1)
|
26
|
+
|
27
|
+
mean_b = b.inject(0.0) {|sum,x| sum + x} / b.size
|
28
|
+
assert_in_delta(1.3, mean_a, 0.1)
|
29
|
+
|
30
|
+
#check variances
|
31
|
+
var_a = a.inject(0.0) {|sum,x| sum + (x - mean_a)**2 } / a.size
|
32
|
+
assert_in_delta(1.0, var_a, 0.1)
|
33
|
+
|
34
|
+
var_b = b.inject(0.0) {|sum,x| sum + (x - mean_b)**2 } / b.size
|
35
|
+
assert_in_delta(1.0, var_b, 0.1)
|
36
|
+
|
37
|
+
#check correlation
|
38
|
+
covariance = a.zip(b).map{|xa,xb| (xa-mean_a)*(xb-mean_b)}.inject(0.0){|sum,x| sum + x} / a.size
|
39
|
+
correlation = covariance / Math.sqrt(var_a * var_b)
|
40
|
+
assert_in_delta(0.3, correlation, 0.1)
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_integer_input
|
45
|
+
mui, sigmai = [1,2], [[1,0.3],[0.3,1]]
|
46
|
+
muf, sigmaf = [1.0,2.0], [[1.0,0.3],[0.3,1.0]]
|
47
|
+
xi = [1,1]
|
48
|
+
xf = [1.0,1.0]
|
49
|
+
dmvnormi = Rubystats::MultivariateNormalDistribution.new(mui,sigmai).pdf(xi)
|
50
|
+
dmvnormf = Rubystats::MultivariateNormalDistribution.new(muf,sigmaf).pdf(xf)
|
51
|
+
assert_in_delta dmvnormi, dmvnormf, 0.00000001
|
52
|
+
end
|
53
|
+
end
|
data/test/tc_norm.rb
CHANGED
@@ -1,14 +1,43 @@
|
|
1
|
-
$:.unshift File.join(File.dirname(__FILE__),
|
2
|
-
require '
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
2
|
+
require 'minitest/autorun'
|
3
3
|
require 'rubystats/normal_distribution'
|
4
4
|
|
5
|
-
class TestNormal <
|
6
|
-
def
|
5
|
+
class TestNormal < MiniTest::Unit::TestCase
|
6
|
+
def test_cdf
|
7
7
|
|
8
8
|
norm = Rubystats::NormalDistribution.new(10,2)
|
9
9
|
cdf = norm.cdf(11)
|
10
10
|
|
11
|
-
assert_equal(
|
12
|
-
|
11
|
+
assert_equal('0.691462461274013', '%.15f' % cdf)
|
12
|
+
refute_nil(norm.rng)
|
13
13
|
end
|
14
|
+
|
15
|
+
def test_distribution
|
16
|
+
norm = Rubystats::NormalDistribution.new(10.0, 1.0)
|
17
|
+
assert_instance_of Float, norm.rng
|
18
|
+
|
19
|
+
total = 10000
|
20
|
+
values =Array.new(total).map{norm.rng.to_i}
|
21
|
+
histogram = Hash[*values.group_by{ |v| v }.flat_map{ |k, v| [k, v.size] }]
|
22
|
+
|
23
|
+
one_sigma = histogram[9] + histogram[10]
|
24
|
+
assert_in_epsilon 0.682689492137 , one_sigma.to_f / total, 0.02, 'the 1-sigma-environment should contain 68.3%'
|
25
|
+
|
26
|
+
two_sigma = one_sigma + histogram[8] + histogram[11]
|
27
|
+
assert_in_epsilon 0.954499736104 , two_sigma.to_f / total, 0.01, 'the 2-sigma-environment should contain 95.4%'
|
28
|
+
|
29
|
+
three_sigma = two_sigma + histogram[7] + histogram[12]
|
30
|
+
assert_in_epsilon 0.997300203937 , three_sigma.to_f / total, 0.005, 'the 3-sigma-environment should contain 99.7%'
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_integer_input
|
34
|
+
meani, sdi = 10, 2
|
35
|
+
meanf, sdf = 10.0, 2.0
|
36
|
+
xi = 11
|
37
|
+
xf = 11.0
|
38
|
+
dnormi = Rubystats::NormalDistribution.new(meani,sdi).pdf(xi)
|
39
|
+
dnormf = Rubystats::NormalDistribution.new(meanf,sdf).pdf(xf)
|
40
|
+
assert_in_delta dnormi, dnormf, 0.00000001
|
41
|
+
end
|
42
|
+
|
14
43
|
end
|