ruby-statistics 4.0.1 → 4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 45aad8d1de15385d2032cf93e0e08a2e8ec96c8bcbfb905c8afd74aec8df92aa
4
- data.tar.gz: eaabdf151901455f82ff68af39b86bc4beb77d234075dbd0ef532877a919bdbf
3
+ metadata.gz: e4cb88874b11506652b269c9ffea61763e5ba7a0379b9d6d24eee591800ece00
4
+ data.tar.gz: a7bf474908dc4911075a2d4ac3d6d8805dedd6bfaccb23e0581875bfc0350c47
5
5
  SHA512:
6
- metadata.gz: f9c6a992a54a50d814b7429a5835b852622b1c88305533ff2237717ad82406391aa1daba15ee66e14cdf0cbd03323edcd3fb1001b31b623618100633d9a26006
7
- data.tar.gz: df6a87efa854ea654d3dc31be61c96d894413b12c7d2b808e37a8920c6c7f43cf9704f449fbcd20ffe22758fd823bdcf7039c6e4754479e3051c8a3d44a89f29
6
+ metadata.gz: 9881d53b1068826f9730cc79370c2c80c079177af9a6ea656ab837aab55b3a2ed62844ba2d5122d23291e4aa70049f9c3e3be2ffda5bfbc1e8299a6399f74d06
7
+ data.tar.gz: fe2cccb772734250ba5bc072fa01990b952d5da5b1cbbc4ee8ca4c1ef59e39cc5b468502b9c78d5c6b6cb5842fa76182c293619e8cfddacb895238f6e23c41b0
@@ -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.190.0
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.190.0
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.190.0
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.190.0
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 `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.
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
- (1.0/left_down) * right
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
@@ -1,3 +1,3 @@
1
1
  module RubyStatistics
2
- VERSION = "4.0.1"
2
+ VERSION = "4.1.0"
3
3
  end
@@ -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.6', '>= 3.6.0'
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.1
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: 2024-08-13 00:00:00.000000000 Z
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.6'
39
+ version: '3.13'
40
40
  - - ">="
41
41
  - !ruby/object:Gem::Version
42
- version: 3.6.0
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.6'
49
+ version: '3.13'
50
50
  - - ">="
51
51
  - !ruby/object:Gem::Version
52
- version: 3.6.0
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