ruby-statistics 4.0.1 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +4 -4
- data/README.md +4 -1
- data/lib/math.rb +47 -0
- data/lib/ruby-statistics/distribution/chi_squared.rb +3 -2
- data/lib/ruby-statistics/distribution/gamma.rb +85 -0
- data/lib/ruby-statistics/distribution/tables/chi_squared.rb +88 -0
- data/lib/ruby-statistics/version.rb +1 -1
- data/ruby-statistics.gemspec +2 -1
- metadata +28 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e4cb88874b11506652b269c9ffea61763e5ba7a0379b9d6d24eee591800ece00
|
4
|
+
data.tar.gz: a7bf474908dc4911075a2d4ac3d6d8805dedd6bfaccb23e0581875bfc0350c47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9881d53b1068826f9730cc79370c2c80c079177af9a6ea656ab837aab55b3a2ed62844ba2d5122d23291e4aa70049f9c3e3be2ffda5bfbc1e8299a6399f74d06
|
7
|
+
data.tar.gz: fe2cccb772734250ba5bc072fa01990b952d5da5b1cbbc4ee8ca4c1ef59e39cc5b468502b9c78d5c6b6cb5842fa76182c293619e8cfddacb895238f6e23c41b0
|
data/.github/workflows/ruby.yml
CHANGED
@@ -10,7 +10,7 @@ jobs:
|
|
10
10
|
steps:
|
11
11
|
- uses: actions/checkout@v4
|
12
12
|
- name: Set up Ruby 3.3
|
13
|
-
uses: ruby/setup-ruby@v1.
|
13
|
+
uses: ruby/setup-ruby@v1.207.0
|
14
14
|
with:
|
15
15
|
ruby-version: 3.3
|
16
16
|
- name: Build and test with Rake
|
@@ -26,7 +26,7 @@ jobs:
|
|
26
26
|
steps:
|
27
27
|
- uses: actions/checkout@v4
|
28
28
|
- name: Set up Ruby 3.2
|
29
|
-
uses: ruby/setup-ruby@v1.
|
29
|
+
uses: ruby/setup-ruby@v1.207.0
|
30
30
|
with:
|
31
31
|
ruby-version: 3.2
|
32
32
|
- name: Build and test with Rake
|
@@ -42,7 +42,7 @@ jobs:
|
|
42
42
|
steps:
|
43
43
|
- uses: actions/checkout@v4
|
44
44
|
- name: Set up Ruby 3.0
|
45
|
-
uses: ruby/setup-ruby@v1.
|
45
|
+
uses: ruby/setup-ruby@v1.207.0
|
46
46
|
with:
|
47
47
|
ruby-version: 3.0
|
48
48
|
- name: Build and test with Rake
|
@@ -58,7 +58,7 @@ jobs:
|
|
58
58
|
steps:
|
59
59
|
- uses: actions/checkout@v4
|
60
60
|
- name: Set up Ruby 3.1
|
61
|
-
uses: ruby/setup-ruby@v1.
|
61
|
+
uses: ruby/setup-ruby@v1.207.0
|
62
62
|
with:
|
63
63
|
ruby-version: 3.1
|
64
64
|
- name: Build and test with Rake
|
data/README.md
CHANGED
@@ -2,7 +2,10 @@
|
|
2
2
|
![](https://github.com/estebanz01/ruby-statistics/actions/workflows/ruby.yml/badge.svg)
|
3
3
|
|
4
4
|
## Note regarding Versions 3.x and 4.x
|
5
|
-
Hola! :wave: right now the gem got an update that introduced a breaking change in master where the Outermost namespace was changed to be `
|
5
|
+
Hola! :wave: right now the gem got an update that introduced a breaking change in master where the Outermost namespace was changed to be `ruby-statistics` instead of `statistics`. This change is in _master_ already and released in version 4.0. If you're relying on branch instead of gem version, you can checkout branch `3.x`. This branch will be supported but no additional features will be added.
|
6
|
+
|
7
|
+
## Note regarding Big Decimal support
|
8
|
+
This gem also provides basic support for `BigDecimal` and the gem is listed as an optional `development` dependency on the gemspec. Since it's no longer supported as a bundled feature since 3.4.0, the functionality around this gem is going to be limited as well. It is not a required dependency to run or use any of the features developed so far. :grin:
|
6
9
|
|
7
10
|
---
|
8
11
|
|
data/lib/math.rb
CHANGED
@@ -57,6 +57,53 @@ module Math
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
+
# Algorithm implementation translated from the ASA147 C++ version https://people.sc.fsu.edu/~jburkardt/cpp_src/asa147/asa147.html
|
61
|
+
# translated from FORTRAN by John Burkardt. Original algorithm written by Chi Leung Lau.
|
62
|
+
# It contains a modification on the error and underflow parameters to use maximum available float number
|
63
|
+
# and it performs the series using `Rational` objects to avoid memory exhaustion and reducing precision errors.
|
64
|
+
#
|
65
|
+
# This algorithm is licensed with MIT license.
|
66
|
+
#
|
67
|
+
# Reference:
|
68
|
+
#
|
69
|
+
# Chi Leung Lau,
|
70
|
+
# Algorithm AS 147:
|
71
|
+
# A Simple Series for the Incomplete Gamma Integral,
|
72
|
+
# Applied Statistics,
|
73
|
+
# Volume 29, Number 1, 1980, pages 113-114.
|
74
|
+
def self.normalised_lower_incomplete_gamma_function(s, x)
|
75
|
+
return 0.0 if s.negative? || x.zero? || x.negative?
|
76
|
+
|
77
|
+
# e = 1.0e-308
|
78
|
+
# uflo = 1.0e-47
|
79
|
+
e = Float::MIN
|
80
|
+
uflo = Float::MIN
|
81
|
+
|
82
|
+
lgamma, sign = Math.lgamma(s + 1.0)
|
83
|
+
arg = s * Math.log(x) - (sign * lgamma) - x
|
84
|
+
|
85
|
+
return 0.0 if arg < Math.log(uflo)
|
86
|
+
|
87
|
+
f = Math.exp(arg).to_r
|
88
|
+
|
89
|
+
return 0.0 if f.zero?
|
90
|
+
|
91
|
+
c = 1r
|
92
|
+
value = 1r
|
93
|
+
a = s.to_r
|
94
|
+
rational_x = x.to_r
|
95
|
+
|
96
|
+
loop do
|
97
|
+
a += 1r
|
98
|
+
c = c * (rational_x / a)
|
99
|
+
value += c
|
100
|
+
|
101
|
+
break if c <= (e * value)
|
102
|
+
end
|
103
|
+
|
104
|
+
(value * f).to_f
|
105
|
+
end
|
106
|
+
|
60
107
|
def self.beta_function(x, y)
|
61
108
|
return 1 if x == 1 && y == 1
|
62
109
|
|
@@ -15,7 +15,8 @@ module RubyStatistics
|
|
15
15
|
1.0 - Math.exp((-1.0 * value / 2.0))
|
16
16
|
else
|
17
17
|
k = degrees_of_freedom/2.0
|
18
|
-
Math.lower_incomplete_gamma_function(k, value/2.0)/Math.gamma(k)
|
18
|
+
# Math.lower_incomplete_gamma_function(k, value/2.0)/Math.gamma(k)
|
19
|
+
Math.normalised_lower_incomplete_gamma_function(k, value / 2.0)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
@@ -27,7 +28,7 @@ module RubyStatistics
|
|
27
28
|
left_down = (2 ** common) * Math.gamma(common)
|
28
29
|
right = (value ** (common - 1)) * Math.exp(-(value/2.0))
|
29
30
|
|
30
|
-
|
31
|
+
right / left_down
|
31
32
|
end
|
32
33
|
|
33
34
|
def mode
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RubyStatistics
|
4
|
+
module Distribution
|
5
|
+
class Gamma
|
6
|
+
attr_reader :shape, :scale, :rate
|
7
|
+
|
8
|
+
def initialize(shape:, scale: nil)
|
9
|
+
@shape = shape
|
10
|
+
@scale = scale
|
11
|
+
|
12
|
+
# If the scale is nil, it means we want the distribution to behave with a rate parameter
|
13
|
+
# instead of a scale parameter
|
14
|
+
@rate = if scale.nil?
|
15
|
+
1.0 / shape
|
16
|
+
else
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def as_rate?
|
22
|
+
scale.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def mean
|
26
|
+
if as_rate?
|
27
|
+
self.shape / self.rate
|
28
|
+
else
|
29
|
+
self.shape * self.scale
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def mode
|
34
|
+
return 0.0 if self.shape < 1.0
|
35
|
+
|
36
|
+
if as_rate?
|
37
|
+
(self.shape - 1.0) / self.rate
|
38
|
+
else
|
39
|
+
(self.shape - 1.0) * self.scale
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def variance
|
44
|
+
if as_rate?
|
45
|
+
self.shape / (self.rate ** 2.0)
|
46
|
+
else
|
47
|
+
self.shape * (self.scale ** 2.0)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def skewness
|
52
|
+
2.0 / Math.sqrt(self.shape)
|
53
|
+
end
|
54
|
+
|
55
|
+
def density_function(x)
|
56
|
+
euler = if as_rate?
|
57
|
+
Math.exp(- self.rate * x)
|
58
|
+
else
|
59
|
+
Math.exp(-x / self.scale.to_r)
|
60
|
+
end
|
61
|
+
|
62
|
+
left = if as_rate?
|
63
|
+
(self.rate ** self.shape).to_r / Math.gamma(self.shape).to_r
|
64
|
+
else
|
65
|
+
1r / (Math.gamma(self.shape).to_r * (self.scale ** self.shape).to_r)
|
66
|
+
end
|
67
|
+
|
68
|
+
left * (x ** (self.shape - 1)) * euler
|
69
|
+
end
|
70
|
+
|
71
|
+
def cumulative_function(x)
|
72
|
+
upper = if as_rate?
|
73
|
+
self.rate * x.to_r
|
74
|
+
else
|
75
|
+
x / self.scale.to_r
|
76
|
+
end
|
77
|
+
|
78
|
+
# left = 1.0 / Math.gamma(self.shape)
|
79
|
+
# right = Math.lower_incomplete_gamma_function(self.shape, upper)
|
80
|
+
# left * right
|
81
|
+
Math.normalised_lower_incomplete_gamma_function(self.shape, upper)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module RubyStatistics
|
2
|
+
module Distribution
|
3
|
+
module Tables
|
4
|
+
class ChiSquared
|
5
|
+
# Values retrieved from the following table provided by the University of Arizona.
|
6
|
+
# https://math.arizona.edu/~jwatkins/chi-square-table.pdf
|
7
|
+
TABLE = [
|
8
|
+
[0.000, 0.000, 0.001, 0.004, 0.016, 2.706, 3.841, 5.024, 6.635, 7.879],
|
9
|
+
[0.010, 0.020, 0.051, 0.103, 0.211, 4.605, 5.991, 7.378, 9.210, 10.597],
|
10
|
+
[0.072, 0.115, 0.216, 0.352, 0.584, 6.251, 7.815, 9.348, 11.345, 12.838],
|
11
|
+
[0.207, 0.297, 0.484, 0.711, 1.064, 7.779, 9.488, 11.143, 13.277, 14.860],
|
12
|
+
[0.412, 0.554, 0.831, 1.145, 1.610, 9.236, 11.070, 12.833, 15.086, 16.750],
|
13
|
+
[0.676, 0.872, 1.237, 1.635, 2.204, 10.645, 12.592, 14.449, 16.812, 18.548],
|
14
|
+
[0.989, 1.239, 1.690, 2.167, 2.833, 12.017, 14.067, 16.013, 18.475, 20.278],
|
15
|
+
[1.344, 1.646, 2.180, 2.733, 3.490, 13.362, 15.507, 17.535, 20.090, 21.955],
|
16
|
+
[1.735, 2.088, 2.700, 3.325, 4.168, 14.684, 16.919, 19.023, 21.666, 23.589],
|
17
|
+
[2.156, 2.558, 3.247, 3.940, 4.865, 15.987, 18.307, 20.483, 23.209, 25.188],
|
18
|
+
[2.603, 3.053, 3.816, 4.575, 5.578, 17.275, 19.675, 21.920, 24.725, 26.757],
|
19
|
+
[3.074, 3.571, 4.404, 5.226, 6.304, 18.549, 21.026, 23.337, 26.217, 28.300],
|
20
|
+
[3.565, 4.107, 5.009, 5.892, 7.042, 19.812, 22.362, 24.736, 27.688, 29.819],
|
21
|
+
[4.075, 4.660, 5.629, 6.571, 7.790, 21.064, 23.685, 26.119, 29.141, 31.319],
|
22
|
+
[4.601, 5.229, 6.262, 7.261, 8.547, 22.307, 24.996, 27.488, 30.578, 32.801],
|
23
|
+
[5.142, 5.812, 6.908, 7.962, 9.312, 23.542, 26.296, 28.845, 32.000, 34.267],
|
24
|
+
[5.697, 6.408, 7.564, 8.672, 10.085, 24.769, 27.587, 30.191, 33.409, 35.718],
|
25
|
+
[6.265, 7.015, 8.231, 9.390, 10.865, 25.989, 28.869, 31.526, 34.805, 37.156],
|
26
|
+
[6.844, 7.633, 8.907, 10.117, 11.651, 27.204, 30.144, 32.852, 36.191, 38.582],
|
27
|
+
[7.434, 8.260, 9.591, 10.851, 12.443, 28.412, 31.410, 34.170, 37.566, 39.997],
|
28
|
+
[8.034, 8.897, 10.283, 11.591, 13.240, 29.615, 32.671, 35.479, 38.932, 41.401],
|
29
|
+
[8.643, 9.542, 10.982, 12.338, 14.041, 30.813, 33.924, 36.781, 40.289, 42.796],
|
30
|
+
[9.260, 10.196, 11.689, 13.091, 14.848, 32.007, 35.172, 38.076, 41.638, 44.181],
|
31
|
+
[9.886, 10.856, 12.401, 13.848, 15.659, 33.196, 36.415, 39.364, 42.980, 45.559],
|
32
|
+
[10.520, 11.524, 13.120, 14.611, 16.473, 34.382, 37.652, 40.646, 44.314, 46.928],
|
33
|
+
[11.160, 12.198, 13.844, 15.379, 17.292, 35.563, 38.885, 41.923, 45.642, 48.290],
|
34
|
+
[11.808, 12.879, 14.573, 16.151, 18.114, 36.741, 40.113, 43.195, 46.963, 49.645],
|
35
|
+
[12.461, 13.565, 15.308, 16.928, 18.939, 37.916, 41.337, 44.461, 48.278, 50.993],
|
36
|
+
[13.121, 14.256, 16.047, 17.708, 19.768, 39.087, 42.557, 45.722, 49.588, 52.336],
|
37
|
+
[13.787, 14.953, 16.791, 18.493, 20.599, 40.256, 43.773, 46.979, 50.892, 53.672],
|
38
|
+
[20.707, 22.164, 24.433, 26.509, 29.051, 51.805, 55.758, 59.342, 63.691, 66.766],
|
39
|
+
[27.991, 29.707, 32.357, 34.764, 37.689, 63.167, 67.505, 71.420, 76.154, 79.490],
|
40
|
+
[35.534, 37.485, 40.482, 43.188, 46.459, 74.397, 79.082, 83.298, 88.379, 91.952],
|
41
|
+
[43.275, 45.442, 48.758, 51.739, 55.329, 85.527, 90.531, 95.023, 100.425, 104.215],
|
42
|
+
[51.172, 53.540, 57.153, 60.391, 64.278, 96.578, 101.879, 106.629, 112.329, 116.321],
|
43
|
+
[59.196, 61.754, 65.647, 69.126, 73.291, 107.565, 113.145, 118.136, 124.116, 128.299],
|
44
|
+
[67.328, 70.065, 74.222, 77.929, 82.358, 118.498, 124.342, 129.561, 135.807, 140.169]
|
45
|
+
].freeze
|
46
|
+
|
47
|
+
ALPHA_HEADER =
|
48
|
+
{
|
49
|
+
0.995 => 0,
|
50
|
+
0.990 => 1,
|
51
|
+
0.975 => 2,
|
52
|
+
0.95 => 3,
|
53
|
+
0.9 => 4,
|
54
|
+
0.1 => 5,
|
55
|
+
0.05 => 6,
|
56
|
+
0.025 => 7,
|
57
|
+
0.01 => 8,
|
58
|
+
0.005 => 9
|
59
|
+
}.freeze
|
60
|
+
|
61
|
+
DEGREES_OF_FREEDOM = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 40, 50, 60, 70, 80, 90, 100].freeze
|
62
|
+
|
63
|
+
# return an array of the alpha values in correct order
|
64
|
+
# i.e. 0.995 -> 0, 0.990 -> 1 etc
|
65
|
+
def self.alpha_values
|
66
|
+
ALPHA_HEADER.keys
|
67
|
+
end
|
68
|
+
|
69
|
+
# Checks if a valid alpha value is passed to look up values
|
70
|
+
def self.valid_alpha?(alpha)
|
71
|
+
self.alpha_values.include?(alpha)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Return a whole column of the distribution table for a certain alpha value
|
75
|
+
def self.alpha_column(alpha)
|
76
|
+
raise "Undefined alpha value." unless self.valid_alpha?(alpha)
|
77
|
+
|
78
|
+
# return an array of hashes for an alpha value
|
79
|
+
# including the degree of freedom for each critical value
|
80
|
+
# i.e. [{df: 1, critival_value: x},...]
|
81
|
+
TABLE.map.with_index do |row, index|
|
82
|
+
{ df: DEGREES_OF_FREEDOM[index], critical_value: row[ALPHA_HEADER[alpha]] }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/ruby-statistics.gemspec
CHANGED
@@ -31,7 +31,8 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.required_ruby_version = '>= 3.0'
|
32
32
|
|
33
33
|
spec.add_development_dependency "rake", '~> 13.0', '>= 12.0.0'
|
34
|
-
spec.add_development_dependency "rspec", '~> 3.
|
34
|
+
spec.add_development_dependency "rspec", '~> 3.13', '>= 3.10.0'
|
35
35
|
spec.add_development_dependency 'byebug', '~> 11.1', '>= 11.1.0'
|
36
36
|
spec.add_development_dependency 'pry', '~> 0.14', '>= 0.14.0'
|
37
|
+
spec.add_development_dependency 'bigdecimal', '~> 3.1', '>= 3.1.9'
|
37
38
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-statistics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0
|
4
|
+
version: 4.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- esteban zapata
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -36,20 +36,20 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '3.
|
39
|
+
version: '3.13'
|
40
40
|
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: 3.
|
42
|
+
version: 3.10.0
|
43
43
|
type: :development
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
47
|
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: '3.
|
49
|
+
version: '3.13'
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: 3.
|
52
|
+
version: 3.10.0
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
54
|
name: byebug
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
@@ -90,6 +90,26 @@ dependencies:
|
|
90
90
|
- - ">="
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: 0.14.0
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: bigdecimal
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '3.1'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 3.1.9
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '3.1'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 3.1.9
|
93
113
|
description: |-
|
94
114
|
This gem is intended to accomplish the same purpose as jStat js library:
|
95
115
|
to provide ruby with statistical capabilities without the need
|
@@ -126,12 +146,14 @@ files:
|
|
126
146
|
- lib/ruby-statistics/distribution/chi_squared.rb
|
127
147
|
- lib/ruby-statistics/distribution/empirical.rb
|
128
148
|
- lib/ruby-statistics/distribution/f.rb
|
149
|
+
- lib/ruby-statistics/distribution/gamma.rb
|
129
150
|
- lib/ruby-statistics/distribution/geometric.rb
|
130
151
|
- lib/ruby-statistics/distribution/logseries.rb
|
131
152
|
- lib/ruby-statistics/distribution/negative_binomial.rb
|
132
153
|
- lib/ruby-statistics/distribution/normal.rb
|
133
154
|
- lib/ruby-statistics/distribution/poisson.rb
|
134
155
|
- lib/ruby-statistics/distribution/t_student.rb
|
156
|
+
- lib/ruby-statistics/distribution/tables/chi_squared.rb
|
135
157
|
- lib/ruby-statistics/distribution/uniform.rb
|
136
158
|
- lib/ruby-statistics/distribution/weibull.rb
|
137
159
|
- lib/ruby-statistics/spearman_rank_coefficient.rb
|