rust 0.3 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,60 @@
1
+ require_relative '../core'
2
+
3
+ module Rust
4
+ class ANOVAModel < RustDatatype
5
+ def self.can_pull?(type, klass)
6
+ return type == "list" && [klass].flatten.include?("aov")
7
+ end
8
+
9
+ def self.pull_variable(variable, type, klass)
10
+ model = RustDatatype.pull_variable(variable, Rust::List)
11
+
12
+ return ANOVAModel.new(model)
13
+ end
14
+
15
+ def load_in_r_as(variable_name)
16
+ @model.load_in_r_as(variable_name)
17
+ end
18
+
19
+ def self.generate(formula, data, **options)
20
+ mapped = ""
21
+ if options.size > 0
22
+ mapped = options.map { |k, v| "#{k}=#{v}" }.join(", ")
23
+ mapped = ", " + mapped
24
+ end
25
+
26
+ Rust.exclusive do
27
+ Rust["aov.data"] = data
28
+ Rust._eval("aov.model.result <- aov(#{formula.to_R}, data=aov.data#{mapped})")
29
+ result = ANOVAModel.new(Rust["aov.model.result"])
30
+ result.r_mirror_to("aov.model.result")
31
+ return result
32
+ end
33
+ end
34
+
35
+ def initialize(model)
36
+ @model = model
37
+ end
38
+
39
+ def model
40
+ @model
41
+ end
42
+
43
+ def summary
44
+ unless @summary
45
+ Rust.exclusive do
46
+ Rust._eval("aov.smr <- summary(#{self.r_mirror})")
47
+ @summary = Rust['aov.smr']
48
+ end
49
+ end
50
+
51
+ return @summary
52
+ end
53
+ end
54
+ end
55
+
56
+ module Rust::RBindings
57
+ def aov(formula, data, **options)
58
+ return ANOVAModel.generate(formula, data, **options)
59
+ end
60
+ end
@@ -0,0 +1,205 @@
1
+ require_relative '../core'
2
+ require_relative '../stats/descriptive'
3
+ require_relative '../stats/correlation'
4
+
5
+ module Rust::Models
6
+ end
7
+
8
+ module Rust::Models::Regression
9
+ class RegressionModel < Rust::RustDatatype
10
+ def self.can_pull?(type, klass)
11
+ # Can only pull specific sub-types
12
+ return false
13
+ end
14
+
15
+ def load_in_r_as(variable_name)
16
+ @model.load_in_r_as(variable_name)
17
+ end
18
+
19
+
20
+ def self.generate(object_type, model_type, dependent_variable, independent_variables, data, **options)
21
+ mapped = ""
22
+ if options.size > 0
23
+ mapped = options.map { |k, v| "#{k}=#{v}" }.join(", ")
24
+ mapped = ", " + mapped
25
+ end
26
+
27
+ formula = Rust::Formula.new(dependent_variable, independent_variables.join(" + "))
28
+
29
+ Rust.exclusive do
30
+ Rust["#{model_type}.data"] = data
31
+
32
+ Rust._eval("#{model_type}.model.result <- #{model_type}(#{formula.to_R}, data=#{model_type}.data#{mapped})")
33
+ result = Rust["#{model_type}.model.result"]
34
+ result.r_mirror_to("#{model_type}.model.result")
35
+
36
+ return result
37
+ end
38
+ end
39
+
40
+ def initialize(model)
41
+ raise StandardError if model.is_a?(RegressionModel)
42
+ @model = model
43
+ end
44
+
45
+ def model
46
+ @model
47
+ end
48
+
49
+ def residuals
50
+ Rust.exclusive do
51
+ @residuals = Rust["residuals(#{self.r_mirror})"] unless @residuals
52
+ end
53
+
54
+ return @residuals
55
+ end
56
+
57
+ def fitted
58
+ Rust.exclusive do
59
+ @fitted = Rust["fitted(#{self.r_mirror})"] unless @fitted
60
+ end
61
+
62
+ return @fitted
63
+ end
64
+
65
+ def actuals
66
+ return self.fitted.zip(self.residuals).map { |couple| couple.sum }
67
+ end
68
+
69
+ def r_2
70
+ return self.summary|"r.squared"
71
+ end
72
+
73
+ def r_2_adjusted
74
+ return self.summary|"adj.r.squared"
75
+ end
76
+
77
+ def mse
78
+ Rust::Descriptive.variance(self.residuals)
79
+ end
80
+
81
+ def coefficients
82
+ a = self.summary|"coefficients"
83
+ end
84
+
85
+ def method_missing(name, *args)
86
+ return model|name.to_s
87
+ end
88
+
89
+ def summary
90
+ unless @summary
91
+ Rust.exclusive do
92
+ @summary = Rust["summary(#{self.r_mirror})"]
93
+ end
94
+ end
95
+
96
+ return @summary
97
+ end
98
+
99
+ def r_hash
100
+ @model.r_hash
101
+ end
102
+ end
103
+
104
+ class LinearRegressionModel < RegressionModel
105
+ def self.can_pull?(type, klass)
106
+ return type == "list" && klass == "lm"
107
+ end
108
+
109
+ def self.pull_variable(variable, type, klass)
110
+ model = Rust::RustDatatype.pull_variable(variable, Rust::List)
111
+
112
+ return LinearRegressionModel.new(model)
113
+ end
114
+
115
+ def self.generate(dependent_variable, independent_variables, data, **options)
116
+ RegressionModel.generate(
117
+ LinearRegressionModel,
118
+ "lm",
119
+ dependent_variable,
120
+ independent_variables,
121
+ data,
122
+ **options
123
+ )
124
+ end
125
+ end
126
+
127
+ class LinearMixedEffectsModel < RegressionModel
128
+ def self.can_pull?(type, klass)
129
+ return type == "S4" && klass == "lmerModLmerTest"
130
+ end
131
+
132
+ def self.pull_priority
133
+ 1
134
+ end
135
+
136
+ def self.pull_variable(variable, type, klass)
137
+ model = Rust::RustDatatype.pull_variable(variable, Rust::S4Class)
138
+
139
+ return LinearMixedEffectsModel.new(model)
140
+ end
141
+
142
+ def summary
143
+ unless @summary
144
+ Rust.exclusive do
145
+ Rust._eval("tmp.summary <- summary(#{self.r_mirror})")
146
+ Rust._eval("mode(tmp.summary$objClass) <- \"list\"")
147
+ Rust._eval("tmp.summary$logLik <- attributes(tmp.summary$logLik)")
148
+ @summary = Rust["tmp.summary"]
149
+ end
150
+ end
151
+
152
+ return @summary
153
+ end
154
+
155
+ def self.generate(dependent_variable, fixed_effects, random_effects, data, **options)
156
+ Rust.prerequisite("lmerTest")
157
+ Rust.prerequisite("rsq")
158
+
159
+ random_effects = random_effects.map { |effect| "(1|#{effect})" }
160
+
161
+ RegressionModel.generate(
162
+ LinearMixedEffectsModel,
163
+ "lmer",
164
+ dependent_variable,
165
+ fixed_effects + random_effects,
166
+ data,
167
+ **options
168
+ )
169
+ end
170
+
171
+ def r_2
172
+ Rust.exclusive do
173
+ Rust._eval("tmp.rsq <- rsq(#{self.r_mirror}, adj=F)")
174
+ return Rust['tmp.rsq']
175
+ end
176
+ end
177
+
178
+ def r_2_adjusted
179
+ Rust.exclusive do
180
+ Rust._eval("tmp.rsq <- rsq(#{self.r_mirror}, adj=T)")
181
+ return Rust['tmp.rsq']
182
+ end
183
+ end
184
+ end
185
+ end
186
+
187
+ module Rust::RBindings
188
+ def lm(formula, data, **options)
189
+ independent = formula.right_part.split("+").map { |v| v.strip }
190
+ return LinearRegressionModel.generate(formula.left_part, independent, data, **options)
191
+ end
192
+
193
+ def lmer(formula, data, **options)
194
+ independent = formula.right_part.split("+").map { |v| v.strip }
195
+
196
+ RegressionModel.generate(
197
+ LinearMixedEffectsModel,
198
+ "lmer",
199
+ formula.left_part,
200
+ independent,
201
+ data,
202
+ **options
203
+ )
204
+ end
205
+ 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,111 @@
1
+ require_relative 'core'
2
+
3
+ module Rust::Plots
4
+ class ScatterPlot < BasePlot
5
+ def initialize(x = nil, y = nil, **options)
6
+ super()
7
+ @series = []
8
+ if x && y
9
+ self.series(x, y, **options)
10
+ end
11
+ end
12
+
13
+ def series(x, y, **options)
14
+ @series << [x, y, options]
15
+
16
+ return self
17
+ end
18
+
19
+ def thickness(t)
20
+ self['lwd'] = t
21
+
22
+ return self
23
+ end
24
+
25
+ def lines()
26
+ self['type'] = "l"
27
+
28
+ return self
29
+ end
30
+
31
+ def points()
32
+ self['type'] = "p"
33
+
34
+ return self
35
+ end
36
+
37
+ def lines_and_points()
38
+ self['type'] = "b"
39
+
40
+ return self
41
+ end
42
+
43
+ protected
44
+ def _show()
45
+ first = true
46
+ palette = self.palette(@series.size)
47
+ i = 0
48
+
49
+ base_options = {}
50
+ unless @options['xlim']
51
+ x_values = @series.map { |v| v[0] }.flatten
52
+ y_values = @series.map { |v| v[1] }.flatten
53
+
54
+ base_options[:xlim] = [x_values.min, x_values.max]
55
+ base_options[:ylim] = [y_values.min, y_values.max]
56
+ end
57
+
58
+ @series.each do |x, y, options|
59
+ options = options.merge(base_options)
60
+ Rust["plotter.x"] = x
61
+ Rust["plotter.y"] = y
62
+
63
+ function = nil
64
+ if first
65
+ function = Rust::Function.new("plot")
66
+ first = false
67
+ else
68
+ function = Rust::Function.new("lines")
69
+ end
70
+
71
+ augmented_options = {}
72
+ augmented_options['col'] = options[:color] || palette[i]
73
+ augmented_options['xlim'] = options[:xlim] if options[:xlim]
74
+ augmented_options['ylim'] = options[:ylim] if options[:ylim]
75
+
76
+ function.options = self._augmented_options(augmented_options)
77
+ function.arguments << Rust::Variable.new("plotter.x")
78
+ function.arguments << Rust::Variable.new("plotter.y")
79
+
80
+ function.call
81
+
82
+ i += 1
83
+ end
84
+
85
+ return self
86
+ end
87
+ end
88
+
89
+ class BarPlot < BasePlot
90
+ def initialize(bars)
91
+ super()
92
+ @bars = bars
93
+ end
94
+
95
+ protected
96
+ def _show()
97
+ Rust["plotter.bars"] = @bars.values
98
+ Rust["plotter.labels"] = @bars.keys
99
+
100
+ Rust._eval("names(plotter.bars) <- plotter.labels")
101
+
102
+ function = Rust::Function.new("barplot")
103
+ function.options = self._augmented_options
104
+ function.arguments << Rust::Variable.new("plotter.bars")
105
+
106
+ function.call
107
+
108
+ return self
109
+ end
110
+ end
111
+ end
@@ -1,11 +1,11 @@
1
- require_relative 'rust-core'
2
- require_relative 'rust-calls'
1
+ require_relative '../core'
3
2
 
4
3
  module Rust::Plots
5
4
  class BasePlot
6
5
  def initialize
7
- @plugins = []
6
+ @renderables = []
8
7
  @options = Rust::Options.new
8
+ @override_options = true
9
9
  end
10
10
 
11
11
  def x_label(label)
@@ -20,6 +20,14 @@ module Rust::Plots
20
20
  return self
21
21
  end
22
22
 
23
+ def palette(size)
24
+ if size <= 1
25
+ return ['black']
26
+ else
27
+ return Rust._pull("hcl.colors(n=#{size})")
28
+ end
29
+ end
30
+
23
31
  def x_range(range)
24
32
  @options['xlim'] = range
25
33
 
@@ -36,7 +44,13 @@ module Rust::Plots
36
44
  @options['xaxt'] = 'n'
37
45
  @options['yaxt'] = 'n'
38
46
 
39
- self.plug(axis)
47
+ self._add_renderable(axis)
48
+
49
+ return self
50
+ end
51
+
52
+ def grid(grid)
53
+ self._add_renderable(grid)
40
54
 
41
55
  return self
42
56
  end
@@ -53,21 +67,25 @@ module Rust::Plots
53
67
  return self
54
68
  end
55
69
 
56
- def plug(plugin)
57
- raise TypeError, "Expected Plugin" unless plugin.is_a?(Plugin)
58
- @plugins << plugin
70
+ def _add_renderable(renderable)
71
+ raise TypeError, "Expected Renderable" unless renderable.is_a?(Renderable)
72
+ @renderables << renderable
59
73
 
60
74
  return self
61
75
  end
62
76
 
63
77
  def []=(option, value)
64
- @options[option] = value
78
+ @options[option.to_s] = value
79
+ end
80
+
81
+ def _do_not_override_options!
82
+ @override_options = false
65
83
  end
66
84
 
67
85
  def show()
68
86
  Rust.exclusive do
69
87
  self._show
70
- self._run_plugins
88
+ self._render_others
71
89
  end
72
90
 
73
91
  return self
@@ -82,7 +100,7 @@ module Rust::Plots
82
100
  Rust.exclusive do
83
101
  pdf_function.call
84
102
  self._show
85
- self._run_plugins
103
+ self._render_others
86
104
  Rust._eval("dev.off()")
87
105
  end
88
106
 
@@ -94,9 +112,9 @@ module Rust::Plots
94
112
  raise "You are trying to show a BasePlot"
95
113
  end
96
114
 
97
- def _run_plugins()
98
- @plugins.each do |plugin|
99
- plugin._run()
115
+ def _render_others()
116
+ @renderables.each do |renderable|
117
+ renderable._render()
100
118
  end
101
119
 
102
120
  return self
@@ -106,7 +124,7 @@ module Rust::Plots
106
124
  result = @options.clone
107
125
 
108
126
  options.each do |key, value|
109
- result[key] = value
127
+ result[key] = value if !result[key] || @override_options
110
128
  end
111
129
 
112
130
  result.select! { |k, v| v != nil }
@@ -115,113 +133,7 @@ module Rust::Plots
115
133
  end
116
134
  end
117
135
 
118
- class ScatterPlot < BasePlot
119
- def initialize(x, y)
120
- super()
121
- @x = x
122
- @y = y
123
- end
124
-
125
- def thickness(t)
126
- self['lwd'] = t
127
-
128
- return self
129
- end
130
-
131
- def lines()
132
- self['type'] = "l"
133
-
134
- return self
135
- end
136
-
137
- def points()
138
- self['type'] = "p"
139
-
140
- return self
141
- end
142
-
143
- def lines_and_points()
144
- self['type'] = "b"
145
-
146
- return self
147
- end
148
-
149
- protected
150
- def _show()
151
- Rust["plotter.x"] = @x
152
- Rust["plotter.y"] = @y
153
-
154
- function = Rust::Function.new("plot")
155
- function.options = self._augmented_options
156
- function.arguments << Rust::Variable.new("plotter.x")
157
- function.arguments << Rust::Variable.new("plotter.y")
158
-
159
- function.call
160
-
161
- return self
162
- end
163
- end
164
-
165
- class DistributionPlot < BasePlot
166
- def initialize
167
- super()
168
- @series = []
169
- end
170
-
171
- def series(data, **options)
172
- @series << [data, options]
173
-
174
- return self
175
- end
176
- end
177
-
178
- class DensityPlot < DistributionPlot
179
- protected
180
- def _show()
181
- first = true
182
- @series.each do |data, options|
183
- Rust["plotter.series"] = data
184
-
185
- if first
186
- first = false
187
- command = "plot"
188
- else
189
- command = "lines"
190
- end
191
-
192
- function = Rust::Function.new(command)
193
- function.options = self._augmented_options({"col" => options[:color]})
194
- function.arguments << Rust::Variable.new("density(plotter.series)")
195
- function.call
196
- end
197
-
198
- return self
199
- end
200
- end
201
-
202
- class BoxPlot < DistributionPlot
203
- protected
204
- def _show()
205
- function = Rust::Function.new("boxplot")
206
-
207
- names = []
208
- @series.each_with_index do |data, i|
209
- series, options = *data
210
- varname = "plotter.series#{i}"
211
- Rust[varname] = series
212
- function.arguments << Rust::Variable.new(varname)
213
- names << (options[:name] || (i+1).to_s)
214
- end
215
-
216
- function.options = self._augmented_options({'names' => names})
217
-
218
- function.call
219
-
220
- return self
221
- end
222
- end
223
-
224
- class Plugin
136
+ class Renderable
225
137
  def initialize
226
138
  @options = Rust::Options.new
227
139
  end
@@ -233,12 +145,12 @@ module Rust::Plots
233
145
  end
234
146
 
235
147
  protected
236
- def _run()
237
- raise "You are trying to run an abstract Plugin"
148
+ def _render()
149
+ raise "You are trying to run an abstract Renderable"
238
150
  end
239
151
  end
240
152
 
241
- class Axis < Plugin
153
+ class Axis < Renderable
242
154
  BELOW = 1
243
155
  LEFT = 2
244
156
  ABOVE = 3
@@ -276,7 +188,7 @@ module Rust::Plots
276
188
  return self
277
189
  end
278
190
 
279
- def _run()
191
+ def _render()
280
192
  function = Rust::Function.new("axis")
281
193
  function.options = @options
282
194
 
@@ -286,7 +198,7 @@ module Rust::Plots
286
198
  end
287
199
  end
288
200
 
289
- class Grid < Plugin
201
+ class Grid < Renderable
290
202
  def initialize
291
203
  super()
292
204
 
@@ -330,7 +242,7 @@ module Rust::Plots
330
242
  return self
331
243
  end
332
244
 
333
- def _run()
245
+ def _render()
334
246
  function = Rust::Function.new("grid")
335
247
 
336
248
  function.arguments << @x
@@ -345,7 +257,30 @@ module Rust::Plots
345
257
  end
346
258
 
347
259
  module Rust::RBindings
348
- def plot(x, y)
349
- Rust::Plots::ScatterPlot.new(x, y).show
260
+ def plot(x, y=(1..x.size).to_a, **options)
261
+ result = Rust::Plots::ScatterPlot.new(x, y)
262
+
263
+ options.each do |k, v|
264
+ result[k] = v
265
+ end
266
+
267
+ result._do_not_override_options!
268
+
269
+ result.show
270
+ end
271
+
272
+ def boxplot(*args, **options)
273
+ result = Rust::Plots::BoxPlot.new
274
+ options.each do |k, v|
275
+ result[k] = v
276
+ end
277
+
278
+ result._do_not_override_options!
279
+
280
+ args.each do |s|
281
+ result.series(s)
282
+ end
283
+
284
+ result.show
350
285
  end
351
286
  end