rust 0.7 → 0.11
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} +23 -1
- data/lib/rust/core/rust.rb +221 -0
- data/lib/rust/core/types/all.rb +4 -0
- data/lib/{rust-core.rb → rust/core/types/dataframe.rb} +159 -331
- data/lib/rust/core/types/datatype.rb +195 -0
- data/lib/rust/core/types/factor.rb +158 -0
- data/lib/rust/core/types/language.rb +199 -0
- data/lib/rust/core/types/list.rb +97 -0
- data/lib/rust/core/types/matrix.rb +155 -0
- data/lib/rust/core/types/s4class.rb +78 -0
- data/lib/rust/core/types/utils.rb +122 -0
- data/lib/rust/core.rb +7 -0
- data/lib/rust/external/robustbase.rb +44 -0
- data/lib/rust/models/all.rb +4 -0
- data/lib/rust/models/anova.rb +77 -0
- data/lib/rust/models/regression.rb +258 -0
- data/lib/rust/plots/all.rb +4 -0
- data/lib/rust/plots/basic-plots.rb +143 -0
- data/lib/{rust-plots.rb → rust/plots/core.rb} +89 -167
- data/lib/rust/plots/distribution-plots.rb +75 -0
- data/lib/rust/stats/all.rb +4 -0
- data/lib/{rust-basics.rb → rust/stats/correlation.rb} +45 -2
- data/lib/{rust-descriptive.rb → rust/stats/descriptive.rb} +52 -3
- data/lib/{rust-effsize.rb → rust/stats/effsize.rb} +28 -13
- data/lib/{rust-probabilities.rb → rust/stats/probabilities.rb} +142 -34
- data/lib/{rust-tests.rb → rust/stats/tests.rb} +178 -92
- data/lib/rust.rb +4 -9
- metadata +32 -13
- data/lib/rust-calls.rb +0 -80
@@ -0,0 +1,258 @@
|
|
1
|
+
require_relative '../core'
|
2
|
+
require_relative '../stats/descriptive'
|
3
|
+
require_relative '../stats/correlation'
|
4
|
+
|
5
|
+
module Rust::Models
|
6
|
+
end
|
7
|
+
|
8
|
+
##
|
9
|
+
# Contains classes that allow to run regression models.
|
10
|
+
|
11
|
+
module Rust::Models::Regression
|
12
|
+
|
13
|
+
##
|
14
|
+
# Generic regression model in R.
|
15
|
+
|
16
|
+
class RegressionModel < Rust::RustDatatype
|
17
|
+
def self.can_pull?(type, klass)
|
18
|
+
# Can only pull specific sub-types
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_in_r_as(variable_name)
|
23
|
+
@model.load_in_r_as(variable_name)
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Generates a new regression model. +object_type+ is the Ruby class of the model object; +model_type+ represents
|
28
|
+
# the type of model at hand; +dependent_variable+ and +independent_variables+ are directly used as part of the
|
29
|
+
# model formula. +data+ represents the dataset to be used. +options+ can be specified and directly passed to the
|
30
|
+
# model.
|
31
|
+
|
32
|
+
def self.generate(object_type, model_type, dependent_variable, independent_variables, data, **options)
|
33
|
+
mapped = ""
|
34
|
+
if options.size > 0
|
35
|
+
mapped = options.map { |k, v| "#{k}=#{v}" }.join(", ")
|
36
|
+
mapped = ", " + mapped
|
37
|
+
end
|
38
|
+
|
39
|
+
formula = Rust::Formula.new(dependent_variable, independent_variables.join(" + "))
|
40
|
+
|
41
|
+
Rust.exclusive do
|
42
|
+
Rust["#{model_type}.data"] = data
|
43
|
+
|
44
|
+
Rust._eval("#{model_type}.model.result <- #{model_type}(#{formula.to_R}, data=#{model_type}.data#{mapped})")
|
45
|
+
result = Rust["#{model_type}.model.result"]
|
46
|
+
result.r_mirror_to("#{model_type}.model.result")
|
47
|
+
|
48
|
+
return result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Creates a new +model+.
|
54
|
+
|
55
|
+
def initialize(model)
|
56
|
+
raise StandardError if model.is_a?(RegressionModel)
|
57
|
+
@model = model
|
58
|
+
end
|
59
|
+
|
60
|
+
def model
|
61
|
+
@model
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Returns the residuals of the model.
|
66
|
+
|
67
|
+
def residuals
|
68
|
+
Rust.exclusive do
|
69
|
+
@residuals = Rust["residuals(#{self.r_mirror})"] unless @residuals
|
70
|
+
end
|
71
|
+
|
72
|
+
return @residuals
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Returns the fitted values of the model.
|
77
|
+
|
78
|
+
def fitted
|
79
|
+
Rust.exclusive do
|
80
|
+
@fitted = Rust["fitted(#{self.r_mirror})"] unless @fitted
|
81
|
+
end
|
82
|
+
|
83
|
+
return @fitted
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Returns the actual values in the dataset.
|
88
|
+
|
89
|
+
def actuals
|
90
|
+
return self.fitted.zip(self.residuals).map { |couple| couple.sum }
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Returns the r-squared of the model.
|
95
|
+
|
96
|
+
def r_2
|
97
|
+
return self.summary|"r.squared"
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Returns the adjusted r-squared of the model.
|
102
|
+
|
103
|
+
def r_2_adjusted
|
104
|
+
return self.summary|"adj.r.squared"
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Returns the mean squared error of the model.
|
109
|
+
|
110
|
+
def mse
|
111
|
+
Rust::Descriptive.variance(self.residuals)
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Returns the coefficients of the model.
|
116
|
+
|
117
|
+
def coefficients
|
118
|
+
a = self.summary|"coefficients"
|
119
|
+
end
|
120
|
+
|
121
|
+
def method_missing(name, *args)
|
122
|
+
return model|name.to_s
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Returns a summary for the model using the summary function in R.
|
127
|
+
|
128
|
+
def summary
|
129
|
+
unless @summary
|
130
|
+
Rust.exclusive do
|
131
|
+
@summary = Rust["summary(#{self.r_mirror})"]
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
return @summary
|
136
|
+
end
|
137
|
+
|
138
|
+
def r_hash
|
139
|
+
@model.r_hash
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
##
|
144
|
+
# Represents a linear regression model in R.
|
145
|
+
|
146
|
+
class LinearRegressionModel < RegressionModel
|
147
|
+
def self.can_pull?(type, klass)
|
148
|
+
return type == "list" && klass == "lm"
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.pull_variable(variable, type, klass)
|
152
|
+
model = Rust::RustDatatype.pull_variable(variable, Rust::List)
|
153
|
+
|
154
|
+
return LinearRegressionModel.new(model)
|
155
|
+
end
|
156
|
+
|
157
|
+
##
|
158
|
+
# Generates a linear regression model, given its +dependent_variable+ and +independent_variables+ and its +data+.
|
159
|
+
# +options+ can be specified and directly passed to the model.
|
160
|
+
|
161
|
+
def self.generate(dependent_variable, independent_variables, data, **options)
|
162
|
+
RegressionModel.generate(
|
163
|
+
LinearRegressionModel,
|
164
|
+
"lm",
|
165
|
+
dependent_variable,
|
166
|
+
independent_variables,
|
167
|
+
data,
|
168
|
+
**options
|
169
|
+
)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
##
|
174
|
+
# Represents a linear mixed effects model in R.
|
175
|
+
|
176
|
+
class LinearMixedEffectsModel < RegressionModel
|
177
|
+
def self.can_pull?(type, klass)
|
178
|
+
return type == "S4" && klass == "lmerModLmerTest"
|
179
|
+
end
|
180
|
+
|
181
|
+
def self.pull_priority
|
182
|
+
1
|
183
|
+
end
|
184
|
+
|
185
|
+
def self.pull_variable(variable, type, klass)
|
186
|
+
model = Rust::RustDatatype.pull_variable(variable, Rust::S4Class)
|
187
|
+
|
188
|
+
return LinearMixedEffectsModel.new(model)
|
189
|
+
end
|
190
|
+
|
191
|
+
def summary
|
192
|
+
unless @summary
|
193
|
+
Rust.exclusive do
|
194
|
+
Rust._eval("tmp.summary <- summary(#{self.r_mirror})")
|
195
|
+
Rust._eval("mode(tmp.summary$objClass) <- \"list\"")
|
196
|
+
Rust._eval("tmp.summary$logLik <- attributes(tmp.summary$logLik)")
|
197
|
+
@summary = Rust["tmp.summary"]
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
return @summary
|
202
|
+
end
|
203
|
+
|
204
|
+
##
|
205
|
+
# Generates a linear mixed effects model, given its +dependent_variable+ and +independent_variables+ and its +data+.
|
206
|
+
# +options+ can be specified and directly passed to the model.
|
207
|
+
|
208
|
+
def self.generate(dependent_variable, fixed_effects, random_effects, data, **options)
|
209
|
+
Rust.prerequisite("lmerTest")
|
210
|
+
Rust.prerequisite("rsq")
|
211
|
+
|
212
|
+
random_effects = random_effects.map { |effect| "(1|#{effect})" }
|
213
|
+
|
214
|
+
RegressionModel.generate(
|
215
|
+
LinearMixedEffectsModel,
|
216
|
+
"lmer",
|
217
|
+
dependent_variable,
|
218
|
+
fixed_effects + random_effects,
|
219
|
+
data,
|
220
|
+
**options
|
221
|
+
)
|
222
|
+
end
|
223
|
+
|
224
|
+
def r_2
|
225
|
+
Rust.exclusive do
|
226
|
+
Rust._eval("tmp.rsq <- rsq(#{self.r_mirror}, adj=F)")
|
227
|
+
return Rust['tmp.rsq']
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def r_2_adjusted
|
232
|
+
Rust.exclusive do
|
233
|
+
Rust._eval("tmp.rsq <- rsq(#{self.r_mirror}, adj=T)")
|
234
|
+
return Rust['tmp.rsq']
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
module Rust::RBindings
|
241
|
+
def lm(formula, data, **options)
|
242
|
+
independent = formula.right_part.split("+").map { |v| v.strip }
|
243
|
+
return LinearRegressionModel.generate(formula.left_part, independent, data, **options)
|
244
|
+
end
|
245
|
+
|
246
|
+
def lmer(formula, data, **options)
|
247
|
+
independent = formula.right_part.split("+").map { |v| v.strip }
|
248
|
+
|
249
|
+
RegressionModel.generate(
|
250
|
+
LinearMixedEffectsModel,
|
251
|
+
"lmer",
|
252
|
+
formula.left_part,
|
253
|
+
independent,
|
254
|
+
data,
|
255
|
+
**options
|
256
|
+
)
|
257
|
+
end
|
258
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
require_relative 'core'
|
2
|
+
|
3
|
+
module Rust::Plots
|
4
|
+
|
5
|
+
##
|
6
|
+
# Allows to create one or many scatter plots.
|
7
|
+
|
8
|
+
class ScatterPlot < BasePlot
|
9
|
+
|
10
|
+
##
|
11
|
+
# Creates a new scatter plot, given two arrays of values +x+ and +y+ for the respective axes (optional).
|
12
|
+
# +options+ can be specified and directly passed to the plot function in R.
|
13
|
+
|
14
|
+
def initialize(x = nil, y = nil, **options)
|
15
|
+
super()
|
16
|
+
@series = []
|
17
|
+
if x && y
|
18
|
+
self.series(x, y, **options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Adds a new data series, given the values for the +x+ and +y+ axes.
|
24
|
+
# +options+ can be specified and directly passed to the plot function in R.
|
25
|
+
|
26
|
+
def series(x, y, **options)
|
27
|
+
@series << [x, y, options]
|
28
|
+
|
29
|
+
return self
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Sets the thickness of the plot lines.
|
34
|
+
|
35
|
+
def thickness(t)
|
36
|
+
self['lwd'] = t
|
37
|
+
|
38
|
+
return self
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Changes the plot type to lines.
|
43
|
+
|
44
|
+
def lines()
|
45
|
+
self['type'] = "l"
|
46
|
+
|
47
|
+
return self
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Changes the plot type to points.
|
52
|
+
|
53
|
+
def points()
|
54
|
+
self['type'] = "p"
|
55
|
+
|
56
|
+
return self
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Changes the plot type to lines and points.
|
61
|
+
|
62
|
+
def lines_and_points()
|
63
|
+
self['type'] = "b"
|
64
|
+
|
65
|
+
return self
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
def _show()
|
70
|
+
first = true
|
71
|
+
palette = self.palette(@series.size)
|
72
|
+
i = 0
|
73
|
+
|
74
|
+
base_options = {}
|
75
|
+
unless @options['xlim']
|
76
|
+
x_values = @series.map { |v| v[0] }.flatten
|
77
|
+
y_values = @series.map { |v| v[1] }.flatten
|
78
|
+
|
79
|
+
base_options[:xlim] = [x_values.min, x_values.max]
|
80
|
+
base_options[:ylim] = [y_values.min, y_values.max]
|
81
|
+
end
|
82
|
+
|
83
|
+
@series.each do |x, y, options|
|
84
|
+
options = options.merge(base_options)
|
85
|
+
Rust["plotter.x"] = x
|
86
|
+
Rust["plotter.y"] = y
|
87
|
+
|
88
|
+
function = nil
|
89
|
+
if first
|
90
|
+
function = Rust::Function.new("plot")
|
91
|
+
first = false
|
92
|
+
else
|
93
|
+
function = Rust::Function.new("lines")
|
94
|
+
end
|
95
|
+
|
96
|
+
augmented_options = {}
|
97
|
+
augmented_options['col'] = options[:color] || palette[i]
|
98
|
+
augmented_options['xlim'] = options[:xlim] if options[:xlim]
|
99
|
+
augmented_options['ylim'] = options[:ylim] if options[:ylim]
|
100
|
+
|
101
|
+
function.options = self._augmented_options(augmented_options)
|
102
|
+
function.arguments << Rust::Variable.new("plotter.x")
|
103
|
+
function.arguments << Rust::Variable.new("plotter.y")
|
104
|
+
|
105
|
+
function.call
|
106
|
+
|
107
|
+
i += 1
|
108
|
+
end
|
109
|
+
|
110
|
+
return self
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Represents a bar plot in R.
|
116
|
+
|
117
|
+
class BarPlot < BasePlot
|
118
|
+
|
119
|
+
##
|
120
|
+
# Creates a new bar plot with the given +bars+ values.
|
121
|
+
|
122
|
+
def initialize(bars)
|
123
|
+
super()
|
124
|
+
@bars = bars
|
125
|
+
end
|
126
|
+
|
127
|
+
protected
|
128
|
+
def _show()
|
129
|
+
Rust["plotter.bars"] = @bars.values
|
130
|
+
Rust["plotter.labels"] = @bars.keys
|
131
|
+
|
132
|
+
Rust._eval("names(plotter.bars) <- plotter.labels")
|
133
|
+
|
134
|
+
function = Rust::Function.new("barplot")
|
135
|
+
function.options = self._augmented_options
|
136
|
+
function.arguments << Rust::Variable.new("plotter.bars")
|
137
|
+
|
138
|
+
function.call
|
139
|
+
|
140
|
+
return self
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|