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.
@@ -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,4 @@
1
+ self_path = File.expand_path(__FILE__)
2
+ Dir.glob(File.dirname(self_path) + "/*.rb").each do |lib|
3
+ require_relative lib unless lib == self_path
4
+ 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