rust 0.3 → 0.9
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 +4 -4
- data/bin/ruby-rust +3 -0
- data/lib/{rust-csv.rb → rust/core/csv.rb} +14 -4
- data/lib/rust/core/rust.rb +157 -0
- data/lib/rust/core/types/all.rb +4 -0
- data/lib/{rust-core.rb → rust/core/types/dataframe.rb} +183 -245
- data/lib/rust/core/types/datatype.rb +161 -0
- data/lib/rust/core/types/factor.rb +131 -0
- data/lib/rust/core/types/language.rb +166 -0
- data/lib/rust/core/types/list.rb +81 -0
- data/lib/rust/core/types/matrix.rb +132 -0
- data/lib/rust/core/types/s4class.rb +59 -0
- data/lib/rust/core/types/utils.rb +109 -0
- data/lib/rust/core.rb +7 -0
- data/lib/rust/models/all.rb +4 -0
- data/lib/rust/models/anova.rb +60 -0
- data/lib/rust/models/regression.rb +205 -0
- data/lib/rust/plots/all.rb +4 -0
- data/lib/rust/plots/basic-plots.rb +111 -0
- data/lib/{rust-plots.rb → rust/plots/core.rb} +64 -129
- data/lib/rust/plots/distribution-plots.rb +62 -0
- data/lib/rust/stats/all.rb +4 -0
- data/lib/{rust-basics.rb → rust/stats/correlation.rb} +11 -5
- data/lib/rust/stats/descriptive.rb +128 -0
- data/lib/{rust-effsize.rb → rust/stats/effsize.rb} +23 -21
- data/lib/rust/stats/probabilities.rb +248 -0
- data/lib/rust/stats/tests.rb +292 -0
- data/lib/rust.rb +4 -8
- metadata +31 -12
- data/lib/rust-calls.rb +0 -69
- data/lib/rust-descriptive.rb +0 -59
- data/lib/rust-tests.rb +0 -165
@@ -0,0 +1,292 @@
|
|
1
|
+
require_relative '../core'
|
2
|
+
|
3
|
+
module Rust::StatisticalTests
|
4
|
+
class Result
|
5
|
+
attr_accessor :name
|
6
|
+
attr_accessor :statistics
|
7
|
+
attr_accessor :pvalue
|
8
|
+
attr_accessor :exact
|
9
|
+
attr_accessor :alpha
|
10
|
+
attr_accessor :hypothesis
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@statistics = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](name)
|
17
|
+
return @statistics[name.to_sym]
|
18
|
+
end
|
19
|
+
|
20
|
+
def []=(name, value)
|
21
|
+
@statistics[name.to_sym] = value
|
22
|
+
end
|
23
|
+
|
24
|
+
def adjusted_pvalue(method='bonferroni')
|
25
|
+
return 1 unless @hypothesis
|
26
|
+
@hypothesis.adjusted_pvalue_for(self, method)
|
27
|
+
end
|
28
|
+
|
29
|
+
def hypothesis=(value)
|
30
|
+
@hypothesis = value
|
31
|
+
@hypothesis.add(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def significant
|
35
|
+
pvalue < alpha
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
return "#{name}. P-value = #{pvalue} " +
|
40
|
+
"(#{significant ? "significant" : "not significant"} w/ alpha = #{alpha}); " +
|
41
|
+
"#{ statistics.map { |k, v| k.to_s + " -> " + v.to_s }.join(", ") }." +
|
42
|
+
(!exact ? " P-value is not exact." : "")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Hypothesis
|
47
|
+
def self.find(title_or_instance)
|
48
|
+
return Hypothesis.new(nil) if title_or_instance == nil
|
49
|
+
|
50
|
+
if title_or_instance.is_a?(String)
|
51
|
+
ObjectSpace.each_object(Hypothesis) do |instance|
|
52
|
+
return instance if instance.title == title_or_instance
|
53
|
+
end
|
54
|
+
|
55
|
+
return Hypothesis.new(title_or_instance)
|
56
|
+
elsif title_or_instance.is_a?(Hypothesis)
|
57
|
+
return title_or_instance
|
58
|
+
end
|
59
|
+
|
60
|
+
raise TypeError, "Expected nil, String or Hypothesis"
|
61
|
+
end
|
62
|
+
|
63
|
+
attr_reader :results
|
64
|
+
attr_reader :title
|
65
|
+
|
66
|
+
def initialize(title)
|
67
|
+
@title = title
|
68
|
+
@results = []
|
69
|
+
end
|
70
|
+
|
71
|
+
def add(result)
|
72
|
+
@results << result
|
73
|
+
end
|
74
|
+
|
75
|
+
def adjusted_pvalue_for(instance, method)
|
76
|
+
p_values = @results.map { |r| r.pvalue }
|
77
|
+
index = @results.index(instance)
|
78
|
+
|
79
|
+
adjusted_pvalues = Rust::StatisticalTests::PValueAdjustment.method(method).adjust(*p_values)
|
80
|
+
|
81
|
+
if adjusted_pvalues.is_a?(Numeric)
|
82
|
+
return adjusted_pvalues
|
83
|
+
else
|
84
|
+
return adjusted_pvalues[index]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class Wilcoxon
|
90
|
+
def self.paired(d1, d2, alpha = 0.05, **options)
|
91
|
+
raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
|
92
|
+
raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
|
93
|
+
raise "The two distributions have different size" if d1.size != d2.size
|
94
|
+
|
95
|
+
Rust.exclusive do
|
96
|
+
Rust["wilcox.a"] = d1
|
97
|
+
Rust["wilcox.b"] = d2
|
98
|
+
|
99
|
+
_, warnings = Rust._eval("wilcox.result = wilcox.test(wilcox.a, wilcox.b, alternative='two.sided', paired=T)", true)
|
100
|
+
result = Rust::StatisticalTests::Result.new
|
101
|
+
result.name = "Wilcoxon Signed-Rank test"
|
102
|
+
result.pvalue = Rust._pull("wilcox.result$p.value")
|
103
|
+
result[:w] = Rust._pull("wilcox.result$statistic")
|
104
|
+
result.exact = !warnings.include?("cannot compute exact p-value with zeroes")
|
105
|
+
result.alpha = alpha
|
106
|
+
result.hypothesis = Rust::StatisticalTests::Hypothesis.find(options[:hypothesis])
|
107
|
+
|
108
|
+
return result
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.unpaired(d1, d2, alpha = 0.05, **options)
|
113
|
+
raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
|
114
|
+
raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
|
115
|
+
|
116
|
+
Rust.exclusive do
|
117
|
+
Rust["wilcox.a"] = d1
|
118
|
+
Rust["wilcox.b"] = d2
|
119
|
+
|
120
|
+
_, warnings = Rust._eval("wilcox.result = wilcox.test(wilcox.a, wilcox.b, alternative='two.sided', paired=F)", true)
|
121
|
+
result = Rust::StatisticalTests::Result.new
|
122
|
+
result.name = "Wilcoxon Ranked-Sum test (a.k.a. Mann–Whitney U test)"
|
123
|
+
result.pvalue = Rust._pull("wilcox.result$p.value")
|
124
|
+
result[:w] = Rust._pull("wilcox.result$statistic")
|
125
|
+
result.exact = !warnings.include?("cannot compute exact p-value with ties")
|
126
|
+
result.alpha = alpha
|
127
|
+
result.hypothesis = Rust::StatisticalTests::Hypothesis.find(options[:hypothesis])
|
128
|
+
|
129
|
+
return result
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class T
|
135
|
+
def self.paired(d1, d2, alpha = 0.05, **options)
|
136
|
+
raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
|
137
|
+
raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
|
138
|
+
raise "The two distributions have different size" if d1.size != d2.size
|
139
|
+
|
140
|
+
Rust.exclusive do
|
141
|
+
Rust["t.a"] = d1
|
142
|
+
Rust["t.b"] = d2
|
143
|
+
|
144
|
+
warnings = Rust._eval("t.result = t.test(t.a, t.b, alternative='two.sided', paired=T)")
|
145
|
+
result = Rust::StatisticalTests::Result.new
|
146
|
+
result.name = "Paired t-test"
|
147
|
+
result.pvalue = Rust._pull("t.result$p.value")
|
148
|
+
result[:t] = Rust._pull("t.result$statistic")
|
149
|
+
result.exact = true
|
150
|
+
result.alpha = alpha
|
151
|
+
result.hypothesis = Rust::StatisticalTests::Hypothesis.find(options[:hypothesis])
|
152
|
+
|
153
|
+
return result
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.unpaired(d1, d2, alpha = 0.05, **options)
|
158
|
+
raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
|
159
|
+
raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
|
160
|
+
|
161
|
+
Rust.exclusive do
|
162
|
+
Rust["t.a"] = d1
|
163
|
+
Rust["t.b"] = d2
|
164
|
+
|
165
|
+
Rust._eval("t.result = t.test(t.a, t.b, alternative='two.sided', paired=F)")
|
166
|
+
result = Rust::StatisticalTests::Result.new
|
167
|
+
result.name = "Welch Two Sample t-test"
|
168
|
+
result.pvalue = Rust._pull("t.result$p.value")
|
169
|
+
result[:t] = Rust._pull("t.result$statistic")
|
170
|
+
result.exact = true
|
171
|
+
result.alpha = alpha
|
172
|
+
result.hypothesis = Rust::StatisticalTests::Hypothesis.find(options[:hypothesis])
|
173
|
+
|
174
|
+
return result
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class Shapiro
|
180
|
+
def self.compute(vector, alpha = 0.05, **options)
|
181
|
+
raise TypeError, "Expecting Array of numerics" if !vector.is_a?(Array) || !vector.all? { |e| e.is_a?(Numeric) }
|
182
|
+
Rust.exclusive do
|
183
|
+
Rust['shapiro.v'] = vector
|
184
|
+
|
185
|
+
Rust._eval("shapiro.result = shapiro.test(shapiro.v)")
|
186
|
+
result = Rust::StatisticalTests::Result.new
|
187
|
+
result.name = "Shapiro-Wilk normality test"
|
188
|
+
result.pvalue = Rust._pull("shapiro.result$p.value")
|
189
|
+
result[:W] = Rust._pull("shapiro.result$statistic")
|
190
|
+
result.exact = true
|
191
|
+
result.alpha = alpha
|
192
|
+
result.hypothesis = Rust::StatisticalTests::Hypothesis.find(options[:hypothesis])
|
193
|
+
|
194
|
+
return result
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
module PValueAdjustment
|
200
|
+
def self.method(name)
|
201
|
+
name = name.to_s
|
202
|
+
case name.downcase
|
203
|
+
when "bonferroni", "b"
|
204
|
+
return Bonferroni
|
205
|
+
when "holm", "h"
|
206
|
+
return Holm
|
207
|
+
when "hochberg"
|
208
|
+
return Hochberg
|
209
|
+
when "hommel"
|
210
|
+
return Hommel
|
211
|
+
when "benjaminihochberg", "bh"
|
212
|
+
return BenjaminiHochberg
|
213
|
+
when "benjaminiyekutieli", "by"
|
214
|
+
return BenjaminiYekutieli
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
class Bonferroni
|
219
|
+
def self.adjust(*p_values)
|
220
|
+
Rust.exclusive do
|
221
|
+
Rust['adjustment.p'] = p_values
|
222
|
+
return Rust._pull("p.adjust(adjustment.p, method=\"bonferroni\")")
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
class Holm
|
228
|
+
def self.adjust(*p_values)
|
229
|
+
Rust.exclusive do
|
230
|
+
Rust['adjustment.p'] = p_values
|
231
|
+
return Rust._pull("p.adjust(adjustment.p, method=\"holm\")")
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
class Hochberg
|
237
|
+
def self.adjust(*p_values)
|
238
|
+
Rust.exclusive do
|
239
|
+
Rust['adjustment.p'] = p_values
|
240
|
+
return Rust._pull("p.adjust(adjustment.p, method=\"hochberg\")")
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
class Hommel
|
246
|
+
def self.adjust(*p_values)
|
247
|
+
Rust.exclusive do
|
248
|
+
Rust['adjustment.p'] = p_values
|
249
|
+
return Rust._pull("p.adjust(adjustment.p, method=\"hommel\")")
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
class BenjaminiHochberg
|
255
|
+
def self.adjust(*p_values)
|
256
|
+
Rust.exclusive do
|
257
|
+
Rust['adjustment.p'] = p_values
|
258
|
+
return Rust._pull("p.adjust(adjustment.p, method=\"BH\")")
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
class BenjaminiYekutieli
|
264
|
+
def self.adjust(*p_values)
|
265
|
+
Rust.exclusive do
|
266
|
+
Rust['adjustment.p'] = p_values
|
267
|
+
return Rust._pull("p.adjust(adjustment.p, method=\"BY\")")
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
module Rust::RBindings
|
275
|
+
def wilcox_test(d1, d2, **args)
|
276
|
+
paired = args[:paired] || false
|
277
|
+
if paired
|
278
|
+
return Rust::StatisticalTests::Wilcoxon.paired(d1, d2)
|
279
|
+
else
|
280
|
+
return Rust::StatisticalTests::Wilcoxon.unpaired(d1, d2)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
def t_test(d1, d2, **args)
|
285
|
+
paired = args[:paired] || false
|
286
|
+
if paired
|
287
|
+
return Rust::StatisticalTests::T.paired(d1, d2)
|
288
|
+
else
|
289
|
+
return Rust::StatisticalTests::T.unpaired(d1, d2)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
data/lib/rust.rb
CHANGED
@@ -1,8 +1,4 @@
|
|
1
|
-
require_relative 'rust
|
2
|
-
require_relative 'rust
|
3
|
-
require_relative 'rust
|
4
|
-
require_relative 'rust
|
5
|
-
require_relative 'rust-effsize'
|
6
|
-
require_relative 'rust-descriptive'
|
7
|
-
require_relative 'rust-plots'
|
8
|
-
require_relative 'rust-calls'
|
1
|
+
require_relative 'rust/core'
|
2
|
+
require_relative 'rust/models/all'
|
3
|
+
require_relative 'rust/plots/all'
|
4
|
+
require_relative 'rust/stats/all'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rust
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.9'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Simone Scalabrino
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rinruby
|
@@ -52,19 +52,38 @@ dependencies:
|
|
52
52
|
version: 1.1.2
|
53
53
|
description: Ruby advanced statistical library based on RinRuby
|
54
54
|
email: s.scalabrino9@gmail.com
|
55
|
-
executables:
|
55
|
+
executables:
|
56
|
+
- ruby-rust
|
56
57
|
extensions: []
|
57
58
|
extra_rdoc_files: []
|
58
59
|
files:
|
59
|
-
-
|
60
|
-
- lib/rust-calls.rb
|
61
|
-
- lib/rust-core.rb
|
62
|
-
- lib/rust-csv.rb
|
63
|
-
- lib/rust-descriptive.rb
|
64
|
-
- lib/rust-effsize.rb
|
65
|
-
- lib/rust-plots.rb
|
66
|
-
- lib/rust-tests.rb
|
60
|
+
- bin/ruby-rust
|
67
61
|
- lib/rust.rb
|
62
|
+
- lib/rust/core.rb
|
63
|
+
- lib/rust/core/csv.rb
|
64
|
+
- lib/rust/core/rust.rb
|
65
|
+
- lib/rust/core/types/all.rb
|
66
|
+
- lib/rust/core/types/dataframe.rb
|
67
|
+
- lib/rust/core/types/datatype.rb
|
68
|
+
- lib/rust/core/types/factor.rb
|
69
|
+
- lib/rust/core/types/language.rb
|
70
|
+
- lib/rust/core/types/list.rb
|
71
|
+
- lib/rust/core/types/matrix.rb
|
72
|
+
- lib/rust/core/types/s4class.rb
|
73
|
+
- lib/rust/core/types/utils.rb
|
74
|
+
- lib/rust/models/all.rb
|
75
|
+
- lib/rust/models/anova.rb
|
76
|
+
- lib/rust/models/regression.rb
|
77
|
+
- lib/rust/plots/all.rb
|
78
|
+
- lib/rust/plots/basic-plots.rb
|
79
|
+
- lib/rust/plots/core.rb
|
80
|
+
- lib/rust/plots/distribution-plots.rb
|
81
|
+
- lib/rust/stats/all.rb
|
82
|
+
- lib/rust/stats/correlation.rb
|
83
|
+
- lib/rust/stats/descriptive.rb
|
84
|
+
- lib/rust/stats/effsize.rb
|
85
|
+
- lib/rust/stats/probabilities.rb
|
86
|
+
- lib/rust/stats/tests.rb
|
68
87
|
homepage: https://github.com/intersimone999/ruby-rust
|
69
88
|
licenses:
|
70
89
|
- GPL-3.0-only
|
@@ -84,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
84
103
|
- !ruby/object:Gem::Version
|
85
104
|
version: '0'
|
86
105
|
requirements: []
|
87
|
-
rubygems_version: 3.
|
106
|
+
rubygems_version: 3.3.15
|
88
107
|
signing_key:
|
89
108
|
specification_version: 4
|
90
109
|
summary: Ruby advanced statistical library
|
data/lib/rust-calls.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
require_relative 'rust-core'
|
2
|
-
|
3
|
-
module Rust
|
4
|
-
class Function
|
5
|
-
attr_reader :name
|
6
|
-
attr_reader :arguments
|
7
|
-
attr_reader :options
|
8
|
-
|
9
|
-
def initialize(name)
|
10
|
-
@function = name
|
11
|
-
@arguments = Arguments.new
|
12
|
-
@options = Options.new
|
13
|
-
end
|
14
|
-
|
15
|
-
def options=(options)
|
16
|
-
raise TypeError, "Expected Options" unless options.is_a?(Options)
|
17
|
-
|
18
|
-
@options = options
|
19
|
-
end
|
20
|
-
|
21
|
-
def arguments=(arguments)
|
22
|
-
raise TypeError, "Expected Arguments" unless options.is_a?(Arguments)
|
23
|
-
|
24
|
-
@arguments = arguments
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_R
|
28
|
-
params = [@arguments.to_R, @options.to_R].select { |v| v != "" }.join(",")
|
29
|
-
return "#@function(#{params})"
|
30
|
-
end
|
31
|
-
|
32
|
-
def call
|
33
|
-
Rust._eval(self.to_R)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class Variable
|
38
|
-
def initialize(name)
|
39
|
-
@name = name
|
40
|
-
end
|
41
|
-
|
42
|
-
def to_R
|
43
|
-
@name
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
class Arguments < Array
|
48
|
-
def to_R
|
49
|
-
return self.map { |v| v.to_R }.join(", ")
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
class Options < Hash
|
54
|
-
def to_R
|
55
|
-
return self.map { |k, v| "#{k}=#{v.to_R}" }.join(", ")
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.from_hash(hash)
|
59
|
-
options = Options.new
|
60
|
-
hash.each do |key, value|
|
61
|
-
options[key.to_s] = value
|
62
|
-
end
|
63
|
-
return options
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
module Rust::RBindings
|
69
|
-
end
|
data/lib/rust-descriptive.rb
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
require 'code-assertions'
|
2
|
-
|
3
|
-
require_relative 'rust-core'
|
4
|
-
|
5
|
-
module Rust::Descriptive
|
6
|
-
class << self
|
7
|
-
def mean(data)
|
8
|
-
raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
|
9
|
-
|
10
|
-
return data.sum.to_f / data.size
|
11
|
-
end
|
12
|
-
|
13
|
-
def standard_deviation(data)
|
14
|
-
raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
|
15
|
-
|
16
|
-
# TODO implement
|
17
|
-
end
|
18
|
-
alias :sd :standard_deviation
|
19
|
-
alias :stddev :standard_deviation
|
20
|
-
|
21
|
-
def variance(data)
|
22
|
-
raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
|
23
|
-
|
24
|
-
# TODO implement
|
25
|
-
end
|
26
|
-
alias :var :variance
|
27
|
-
|
28
|
-
def median(data)
|
29
|
-
raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
|
30
|
-
|
31
|
-
sorted = data.sort
|
32
|
-
if data.size == 0
|
33
|
-
return Float::NAN
|
34
|
-
elsif data.size.odd?
|
35
|
-
return sorted[data.size / 2]
|
36
|
-
else
|
37
|
-
i = (data.size / 2)
|
38
|
-
return (sorted[i - 1] + sorted[i]) / 2.0
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def quantile(data, percentiles=[0.0, 0.25, 0.5, 0.75, 1.0])
|
43
|
-
raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
|
44
|
-
raise TypeError, "Expecting Array of numerics" if !percentiles.is_a?(Array) || !percentiles.all? { |e| e.is_a?(Numeric) }
|
45
|
-
raise "Percentiles outside the range: #{percentiles}" if percentiles.any? { |e| !e.between?(0, 1) }
|
46
|
-
|
47
|
-
Rust.exclusive do
|
48
|
-
Rust['descriptive.data'] = data
|
49
|
-
Rust['descriptive.percs'] = percentiles
|
50
|
-
|
51
|
-
call_result = Rust._pull("quantile(descriptive.data, descriptive.percs)")
|
52
|
-
assert { call_result.is_a?(Array) }
|
53
|
-
assert { call_result.size == percentiles.size }
|
54
|
-
|
55
|
-
return percentiles.zip(call_result).to_h
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
data/lib/rust-tests.rb
DELETED
@@ -1,165 +0,0 @@
|
|
1
|
-
require_relative 'rust-core'
|
2
|
-
|
3
|
-
module Rust::StatisticalTests
|
4
|
-
class Result
|
5
|
-
attr_accessor :name
|
6
|
-
attr_accessor :statistics
|
7
|
-
attr_accessor :pvalue
|
8
|
-
attr_accessor :exact
|
9
|
-
attr_accessor :alpha
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@statistics = {}
|
13
|
-
end
|
14
|
-
|
15
|
-
def [](name)
|
16
|
-
return @statistics[name.to_sym]
|
17
|
-
end
|
18
|
-
|
19
|
-
def []=(name, value)
|
20
|
-
@statistics[name.to_sym] = value
|
21
|
-
end
|
22
|
-
|
23
|
-
def significant
|
24
|
-
pvalue < alpha
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_s
|
28
|
-
return "#{name}. P-value = #{pvalue} " +
|
29
|
-
"(#{significant ? "significant" : "not significant"} w/ alpha = #{alpha}); " +
|
30
|
-
"#{ statistics.map { |k, v| k.to_s + " -> " + v.to_s }.join(", ") }." +
|
31
|
-
(!exact ? " P-value is not exact." : "")
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
module Rust::StatisticalTests::Wilcoxon
|
37
|
-
class << self
|
38
|
-
def paired(d1, d2, alpha = 0.05)
|
39
|
-
raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
|
40
|
-
raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
|
41
|
-
raise "The two distributions have different size" if d1.size != d2.size
|
42
|
-
|
43
|
-
Rust.exclusive do
|
44
|
-
Rust["wilcox.a"] = d1
|
45
|
-
Rust["wilcox.b"] = d2
|
46
|
-
|
47
|
-
_, warnings = Rust._eval("wilcox.result = wilcox.test(wilcox.a, wilcox.b, alternative='two.sided', paired=T)", true)
|
48
|
-
result = Rust::StatisticalTests::Result.new
|
49
|
-
result.name = "Wilcoxon Signed-Rank test"
|
50
|
-
result.pvalue = Rust._pull("wilcox.result$p.value")
|
51
|
-
result[:w] = Rust._pull("wilcox.result$statistic")
|
52
|
-
result.exact = !warnings.include?("cannot compute exact p-value with zeroes")
|
53
|
-
result.alpha = alpha
|
54
|
-
|
55
|
-
return result
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def unpaired(d1, d2, alpha = 0.05)
|
60
|
-
raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
|
61
|
-
raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
|
62
|
-
|
63
|
-
Rust.exclusive do
|
64
|
-
Rust["wilcox.a"] = d1
|
65
|
-
Rust["wilcox.b"] = d2
|
66
|
-
|
67
|
-
_, warnings = Rust._eval("wilcox.result = wilcox.test(wilcox.a, wilcox.b, alternative='two.sided', paired=F)", true)
|
68
|
-
result = Rust::StatisticalTests::Result.new
|
69
|
-
result.name = "Wilcoxon Ranked-Sum test (a.k.a. Mann–Whitney U test)"
|
70
|
-
result.pvalue = Rust._pull("wilcox.result$p.value")
|
71
|
-
result[:w] = Rust._pull("wilcox.result$statistic")
|
72
|
-
result.exact = !warnings.include?("cannot compute exact p-value with ties")
|
73
|
-
result.alpha = alpha
|
74
|
-
|
75
|
-
return result
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
module Rust::StatisticalTests::T
|
82
|
-
class << self
|
83
|
-
def paired(d1, d2, alpha = 0.05)
|
84
|
-
raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
|
85
|
-
raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
|
86
|
-
raise "The two distributions have different size" if d1.size != d2.size
|
87
|
-
|
88
|
-
Rust.exclusive do
|
89
|
-
Rust["t.a"] = d1
|
90
|
-
Rust["t.b"] = d2
|
91
|
-
|
92
|
-
warnings = Rust._eval("t.result = t.test(t.a, t.b, alternative='two.sided', paired=T)")
|
93
|
-
result = Rust::StatisticalTests::Result.new
|
94
|
-
result.name = "Paired t-test"
|
95
|
-
result.pvalue = Rust._pull("t.result$p.value")
|
96
|
-
result[:t] = Rust._pull("t.result$statistic")
|
97
|
-
result.exact = true
|
98
|
-
result.alpha = alpha
|
99
|
-
|
100
|
-
return result
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
def unpaired(d1, d2, alpha = 0.05)
|
105
|
-
raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
|
106
|
-
raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
|
107
|
-
|
108
|
-
Rust.exclusive do
|
109
|
-
Rust["t.a"] = d1
|
110
|
-
Rust["t.b"] = d2
|
111
|
-
|
112
|
-
Rust._eval("t.result = t.test(t.a, t.b, alternative='two.sided', paired=F)")
|
113
|
-
result = Rust::StatisticalTests::Result.new
|
114
|
-
result.name = "Welch Two Sample t-test"
|
115
|
-
result.pvalue = Rust._pull("t.result$p.value")
|
116
|
-
result[:t] = Rust._pull("t.result$statistic")
|
117
|
-
result.exact = true
|
118
|
-
result.alpha = alpha
|
119
|
-
|
120
|
-
return result
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
module Rust::StatisticalTests::Shapiro
|
127
|
-
class << self
|
128
|
-
def compute(vector, alpha = 0.05)
|
129
|
-
raise TypeError, "Expecting Array of numerics" if !vector.is_a?(Array) || !vector.all? { |e| e.is_a?(Numeric) }
|
130
|
-
Rust.exclusive do
|
131
|
-
Rust['shapiro.v'] = vector
|
132
|
-
|
133
|
-
Rust._eval("shapiro.result = shapiro.test(shapiro.v)")
|
134
|
-
result = Rust::StatisticalTests::Result.new
|
135
|
-
result.name = "Shapiro-Wilk normality test"
|
136
|
-
result.pvalue = Rust._pull("shapiro.result$p.value")
|
137
|
-
result[:W] = Rust._pull("shapiro.result$statistic")
|
138
|
-
result.exact = true
|
139
|
-
result.alpha = alpha
|
140
|
-
|
141
|
-
return result
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
module Rust::RBindings
|
148
|
-
def wilcox_test(d1, d2, **args)
|
149
|
-
paired = args[:paired] || false
|
150
|
-
if paired
|
151
|
-
return Rust::StatisticalTests::Wilcoxon.paired(d1, d2)
|
152
|
-
else
|
153
|
-
return Rust::StatisticalTests::Wilcoxon.unpaired(d1, d2)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
def t_test(d1, d2, **args)
|
158
|
-
paired = args[:paired] || false
|
159
|
-
if paired
|
160
|
-
return Rust::StatisticalTests::T.paired(d1, d2)
|
161
|
-
else
|
162
|
-
return Rust::StatisticalTests::T.unpaired(d1, d2)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|