rust 0.7 → 0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,26 +1,45 @@
1
- require_relative 'rust-core'
2
- require_relative 'rust-calls'
1
+ require_relative '../core'
2
+
3
+ ##
4
+ # Module that contains classes for plotting.
3
5
 
4
6
  module Rust::Plots
7
+
8
+ ##
9
+ # Represents a generic plot in R.
10
+
5
11
  class BasePlot
12
+
13
+ ##
14
+ # Creates a new base plot object.
15
+
6
16
  def initialize
7
17
  @renderables = []
8
18
  @options = Rust::Options.new
9
19
  @override_options = true
10
20
  end
11
21
 
22
+ ##
23
+ # Sets the x-axis label.
24
+
12
25
  def x_label(label)
13
26
  @options['xlab'] = label
14
27
 
15
28
  return self
16
29
  end
17
30
 
31
+ ##
32
+ # Sets the y-axis label.
33
+
18
34
  def y_label(label)
19
35
  @options['ylab'] = label
20
36
 
21
37
  return self
22
38
  end
23
39
 
40
+ ##
41
+ # Returns a color palette of the given +size+.
42
+
24
43
  def palette(size)
25
44
  if size <= 1
26
45
  return ['black']
@@ -29,17 +48,28 @@ module Rust::Plots
29
48
  end
30
49
  end
31
50
 
51
+ ##
52
+ # Sets the limits for the x-axis.
53
+
32
54
  def x_range(range)
33
55
  @options['xlim'] = range
34
56
 
35
57
  return self
36
58
  end
59
+ alias :xlim :x_range
60
+
61
+ ##
62
+ # Sets the limits for the y-axis.
37
63
 
38
64
  def y_range(range)
39
65
  @options['ylim'] = range
40
66
 
41
67
  return self
42
68
  end
69
+ alias :ylim :y_range
70
+
71
+ ##
72
+ # Adds an +axis+ to show instead of the default ones.
43
73
 
44
74
  def axis(axis)
45
75
  @options['xaxt'] = 'n'
@@ -50,18 +80,27 @@ module Rust::Plots
50
80
  return self
51
81
  end
52
82
 
83
+ ##
84
+ # Shows the given +grid+.
85
+
53
86
  def grid(grid)
54
87
  self._add_renderable(grid)
55
88
 
56
89
  return self
57
90
  end
58
91
 
92
+ ##
93
+ # Sets the +title+ of the plot.
94
+
59
95
  def title(title)
60
96
  @options['main'] = title
61
97
 
62
98
  return self
63
99
  end
64
100
 
101
+ ##
102
+ # Sets the +color+ of the plot.
103
+
65
104
  def color(color)
66
105
  @options['col'] = color
67
106
 
@@ -75,6 +114,9 @@ module Rust::Plots
75
114
  return self
76
115
  end
77
116
 
117
+ ##
118
+ # Sets any R +option+ with the given +value+.
119
+
78
120
  def []=(option, value)
79
121
  @options[option.to_s] = value
80
122
  end
@@ -83,6 +125,9 @@ module Rust::Plots
83
125
  @override_options = false
84
126
  end
85
127
 
128
+ ##
129
+ # Shows the plot in a window.
130
+
86
131
  def show()
87
132
  Rust.exclusive do
88
133
  self._show
@@ -92,6 +137,9 @@ module Rust::Plots
92
137
  return self
93
138
  end
94
139
 
140
+ ##
141
+ # Prints the plot on a PDF file at path. +options+ can be specified for the PDF (e.g., width and height).
142
+
95
143
  def pdf(path, **options)
96
144
  pdf_function = Rust::Function.new("pdf")
97
145
  pdf_function.options = Rust::Options.from_hash(options)
@@ -134,178 +182,21 @@ module Rust::Plots
134
182
  end
135
183
  end
136
184
 
137
- class ScatterPlot < BasePlot
138
- def initialize(x = nil, y = nil, **options)
139
- super()
140
- @series = []
141
- if x && y
142
- self.series(x, y, options)
143
- end
144
- end
145
-
146
- def series(x, y, **options)
147
- @series << [x, y, options]
148
-
149
- return self
150
- end
151
-
152
- def thickness(t)
153
- self['lwd'] = t
154
-
155
- return self
156
- end
157
-
158
- def lines()
159
- self['type'] = "l"
160
-
161
- return self
162
- end
163
-
164
- def points()
165
- self['type'] = "p"
166
-
167
- return self
168
- end
169
-
170
- def lines_and_points()
171
- self['type'] = "b"
172
-
173
- return self
174
- end
175
-
176
- protected
177
- def _show()
178
- first = true
179
- palette = self.palette(@series.size)
180
- i = 0
181
-
182
- base_options = {}
183
- unless @options['xlim']
184
- x_values = @series.map { |v| v[0] }.flatten
185
- y_values = @series.map { |v| v[1] }.flatten
186
-
187
- base_options[:xlim] = [x_values.min, x_values.max]
188
- base_options[:ylim] = [y_values.min, y_values.max]
189
- end
190
-
191
- @series.each do |x, y, options|
192
- options = options.merge(base_options)
193
- Rust["plotter.x"] = x
194
- Rust["plotter.y"] = y
195
-
196
- function = nil
197
- if first
198
- function = Rust::Function.new("plot")
199
- first = false
200
- else
201
- function = Rust::Function.new("lines")
202
- end
203
-
204
- augmented_options = {}
205
- augmented_options['col'] = options[:color] || palette[i]
206
- augmented_options['xlim'] = options[:xlim] if options[:xlim]
207
- augmented_options['ylim'] = options[:ylim] if options[:ylim]
208
-
209
- function.options = self._augmented_options(augmented_options)
210
- function.arguments << Rust::Variable.new("plotter.x")
211
- function.arguments << Rust::Variable.new("plotter.y")
212
-
213
- function.call
214
-
215
- i += 1
216
- end
217
-
218
- return self
219
- end
220
- end
185
+ ##
186
+ # Represents any element that can be rendered in a plot (e.g., axes or grids).
221
187
 
222
- class BarPlot < BasePlot
223
- def initialize(bars)
224
- super()
225
- @bars = bars
226
- end
188
+ class Renderable
227
189
 
228
- protected
229
- def _show()
230
- Rust["plotter.bars"] = @bars.values
231
- Rust["plotter.labels"] = @bars.keys
232
-
233
- Rust._eval("names(plotter.bars) <- plotter.labels")
234
-
235
- function = Rust::Function.new("barplot")
236
- function.options = self._augmented_options
237
- function.arguments << Rust::Variable.new("plotter.bars")
238
-
239
- function.call
240
-
241
- return self
242
- end
243
- end
244
-
245
- class DistributionPlot < BasePlot
246
- def initialize
247
- super()
248
- @series = []
249
- end
190
+ ##
191
+ # Creates a new empty renderable object.
250
192
 
251
- def series(data, **options)
252
- @series << [data, options]
253
-
254
- return self
255
- end
256
- end
257
-
258
- class DensityPlot < DistributionPlot
259
- protected
260
- def _show()
261
- first = true
262
- @series.each do |data, options|
263
- Rust["plotter.series"] = data
264
-
265
- if first
266
- first = false
267
- command = "plot"
268
- else
269
- command = "lines"
270
- end
271
-
272
- function = Rust::Function.new(command)
273
- function.options = self._augmented_options({"col" => options[:color]})
274
- function.arguments << Rust::Variable.new("density(plotter.series)")
275
- function.call
276
- end
277
-
278
- return self
279
- end
280
- end
281
-
282
- class BoxPlot < DistributionPlot
283
- protected
284
- def _show()
285
- function = Rust::Function.new("boxplot")
286
-
287
- names = []
288
- @series.each_with_index do |data, i|
289
- series, options = *data
290
- varname = "plotter.series#{i}"
291
- Rust[varname] = series
292
- function.arguments << Rust::Variable.new(varname)
293
- names << (options[:name] || (i+1).to_s)
294
- end
295
-
296
- function.options = self._augmented_options({'names' => names})
297
-
298
- function.call
299
-
300
- return self
301
- end
302
- end
303
-
304
- class Renderable
305
193
  def initialize
306
194
  @options = Rust::Options.new
307
195
  end
308
196
 
197
+ ##
198
+ # Sets an option for the renderable object.
199
+
309
200
  def []=(option, value)
310
201
  @options[option] = value
311
202
 
@@ -318,12 +209,18 @@ module Rust::Plots
318
209
  end
319
210
  end
320
211
 
212
+ ##
213
+ # Represents an axis for a plot.
214
+
321
215
  class Axis < Renderable
322
216
  BELOW = 1
323
217
  LEFT = 2
324
218
  ABOVE = 3
325
219
  RIGHT = 4
326
220
 
221
+ ##
222
+ # Creates a new axis at the given +side+ (constants BELOW, LEFT, ABOVE, and RIGHT are available).
223
+
327
224
  def initialize(side)
328
225
  super()
329
226
 
@@ -366,7 +263,14 @@ module Rust::Plots
366
263
  end
367
264
  end
368
265
 
266
+ ##
267
+ # Represents a grid for a plot.
268
+
369
269
  class Grid < Renderable
270
+
271
+ ##
272
+ # Creates a new grid
273
+
370
274
  def initialize
371
275
  super()
372
276
 
@@ -374,36 +278,54 @@ module Rust::Plots
374
278
  @y = Float::NAN
375
279
  end
376
280
 
281
+ ##
282
+ # Sets the x intervals.
283
+
377
284
  def x(value)
378
285
  @x = value
379
286
 
380
287
  return self
381
288
  end
382
289
 
290
+ ##
291
+ # Sets the y intervals.
292
+
383
293
  def y(value)
384
294
  @y = value
385
295
 
386
296
  return self
387
297
  end
388
298
 
299
+ ##
300
+ # Automatically sets the x intervals.
301
+
389
302
  def auto_x
390
303
  @x = nil
391
304
 
392
305
  return self
393
306
  end
394
307
 
308
+ ##
309
+ # Automatically sets the y intervals.
310
+
395
311
  def auto_y
396
312
  @y = nil
397
313
 
398
314
  return self
399
315
  end
400
316
 
317
+ ##
318
+ # Hides x axis lines.
319
+
401
320
  def hide_x
402
321
  @x = Float::NAN
403
322
 
404
323
  return self
405
324
  end
406
325
 
326
+ ##
327
+ # Hides y axis lines.
328
+
407
329
  def hide_y
408
330
  @y = Float::NAN
409
331
 
@@ -0,0 +1,75 @@
1
+ require_relative 'core'
2
+
3
+ module Rust::Plots
4
+
5
+ ##
6
+ # Represents any distribution-related plot (e.g., boxplots).
7
+
8
+ class DistributionPlot < BasePlot
9
+ def initialize
10
+ super()
11
+ @series = []
12
+ end
13
+
14
+ ##
15
+ # Adds a series of data points. +options+ can be specified and directly passed to the R plotting function.
16
+
17
+ def series(data, **options)
18
+ @series << [data, options]
19
+
20
+ return self
21
+ end
22
+ end
23
+
24
+ ##
25
+ # Represents a density plot in R.
26
+
27
+ class DensityPlot < DistributionPlot
28
+ protected
29
+ def _show()
30
+ first = true
31
+ @series.each do |data, options|
32
+ Rust["plotter.series"] = data
33
+
34
+ if first
35
+ first = false
36
+ command = "plot"
37
+ else
38
+ command = "lines"
39
+ end
40
+
41
+ function = Rust::Function.new(command)
42
+ function.options = self._augmented_options({"col" => options[:color]})
43
+ function.arguments << Rust::Variable.new("density(plotter.series)")
44
+ function.call
45
+ end
46
+
47
+ return self
48
+ end
49
+ end
50
+
51
+ ##
52
+ # Represents a boxplot in R.
53
+
54
+ class BoxPlot < DistributionPlot
55
+ protected
56
+ def _show()
57
+ function = Rust::Function.new("boxplot")
58
+
59
+ names = []
60
+ @series.each_with_index do |data, i|
61
+ series, options = *data
62
+ varname = "plotter.series#{i}"
63
+ Rust[varname] = series
64
+ function.arguments << Rust::Variable.new(varname)
65
+ names << (options[:name] || (i+1).to_s)
66
+ end
67
+
68
+ function.options = self._augmented_options({'names' => names})
69
+
70
+ function.call
71
+
72
+ return self
73
+ end
74
+ end
75
+ 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
@@ -1,7 +1,18 @@
1
- require_relative 'rust-core'
1
+ require_relative '../core'
2
+
3
+ ##
4
+ # Module containing all the correlation-related statistics.
2
5
 
3
6
  module Rust::Correlation
7
+
8
+ ##
9
+ # Pearson correlation utility methods.
10
+
4
11
  class Pearson
12
+
13
+ ##
14
+ # Runs the Pearson correlation test between +d1+ and +d2+.
15
+
5
16
  def self.test(d1, d2)
6
17
  raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
7
18
  raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
@@ -23,12 +34,22 @@ module Rust::Correlation
23
34
  end
24
35
  end
25
36
 
37
+ ##
38
+ # Returns the Pearson correlation index between +d1+ and +d2+
39
+
26
40
  def self.estimate(d1, d2)
27
41
  self.test(d1, d2).correlation
28
42
  end
29
43
  end
30
44
 
45
+ ##
46
+ # Spearman correlation utility methods.
47
+
31
48
  class Spearman
49
+
50
+ ##
51
+ # Runs the Spearman correlation test between +d1+ and +d2+.
52
+
32
53
  def self.test(d1, d2)
33
54
  raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
34
55
  raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
@@ -50,12 +71,22 @@ module Rust::Correlation
50
71
  end
51
72
  end
52
73
 
74
+ ##
75
+ # Returns the Spearman correlation index between +d1+ and +d2+
76
+
53
77
  def self.estimate(d1, d2)
54
78
  self.test(d1, d2).correlation
55
79
  end
56
80
  end
57
81
 
82
+ ##
83
+ # Kendall correlation utility methods.
84
+
58
85
  class Kendall
86
+
87
+ ##
88
+ # Runs the Kendall correlation test between +d1+ and +d2+.
89
+
59
90
  def self.test(d1, d2)
60
91
  raise TypeError, "Expecting Array of numerics" if !d1.is_a?(Array) || !d1.all? { |e| e.is_a?(Numeric) }
61
92
  raise TypeError, "Expecting Array of numerics" if !d2.is_a?(Array) || !d2.all? { |e| e.is_a?(Numeric) }
@@ -64,7 +95,7 @@ module Rust::Correlation
64
95
  Rust['correlation.a'] = d1
65
96
  Rust['correlation.b'] = d2
66
97
 
67
- _, warnings = Rust._eval("correlation.result <- cor.test(correlation.a, correlation.b, method='p')", true)
98
+ _, warnings = Rust._eval("correlation.result <- cor.test(correlation.a, correlation.b, method='k')", true)
68
99
 
69
100
  result = Result.new
70
101
  result.name = "Kendall's rank correlation tau"
@@ -77,11 +108,17 @@ module Rust::Correlation
77
108
  end
78
109
  end
79
110
 
111
+ ##
112
+ # Returns the Kendall correlation index between +d1+ and +d2+
113
+
80
114
  def self.estimate(d1, d2)
81
115
  self.test(d1, d2).correlation
82
116
  end
83
117
  end
84
118
 
119
+ ##
120
+ # Result of a correlation test.
121
+
85
122
  class Result
86
123
  attr_accessor :name
87
124
  attr_accessor :statistics
@@ -96,10 +133,16 @@ module Rust::Correlation
96
133
  @exact = true
97
134
  end
98
135
 
136
+ ##
137
+ # Returns the statistic with the specified +name+.
138
+
99
139
  def [](name)
100
140
  return @statistics[name.to_sym]
101
141
  end
102
142
 
143
+ ##
144
+ # Sets the +value+ for the the statistic with the specified +name+.
145
+
103
146
  def []=(name, value)
104
147
  @statistics[name.to_sym] = value
105
148
  end
@@ -1,15 +1,23 @@
1
- require 'code-assertions'
1
+ require_relative '../core'
2
2
 
3
- require_relative 'rust-core'
3
+ ##
4
+ # Module containing utilities for descriptive statistics.
4
5
 
5
6
  module Rust::Descriptive
6
7
  class << self
8
+
9
+ ##
10
+ # Computes the arithmetic mean of the given +data+.
11
+
7
12
  def mean(data)
8
13
  raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
9
14
 
10
15
  return data.sum.to_f / data.size
11
16
  end
12
17
 
18
+ ##
19
+ # Computes the standard deviation of the given +data+.
20
+
13
21
  def standard_deviation(data)
14
22
  raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
15
23
 
@@ -18,6 +26,9 @@ module Rust::Descriptive
18
26
  alias :sd :standard_deviation
19
27
  alias :stddev :standard_deviation
20
28
 
29
+ ##
30
+ # Computes the variance of the given +data+.
31
+
21
32
  def variance(data)
22
33
  raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
23
34
  return Float::NAN if data.size < 2
@@ -27,6 +38,9 @@ module Rust::Descriptive
27
38
  end
28
39
  alias :var :variance
29
40
 
41
+ ##
42
+ # Computes the median of the given +data+.
43
+
30
44
  def median(data)
31
45
  raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
32
46
 
@@ -41,13 +55,19 @@ module Rust::Descriptive
41
55
  end
42
56
  end
43
57
 
58
+ ##
59
+ # Sums the given +data+.
60
+
44
61
  def sum(data)
45
62
  raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
46
63
 
47
64
  return data.sum
48
65
  end
49
66
 
50
- def quantile(data, percentiles=[0.0, 0.25, 0.5, 0.75, 1.0])
67
+ ##
68
+ # Returns the quantiles of the given +data+, given the +percentiles+ (optional).
69
+
70
+ def quantile(data, percentiles = [0.0, 0.25, 0.5, 0.75, 1.0])
51
71
  raise TypeError, "Expecting Array of numerics" if !data.is_a?(Array) || !data.all? { |e| e.is_a?(Numeric) }
52
72
  raise TypeError, "Expecting Array of numerics" if !percentiles.is_a?(Array) || !percentiles.all? { |e| e.is_a?(Numeric) }
53
73
  raise "Percentiles outside the range: #{percentiles}" if percentiles.any? { |e| !e.between?(0, 1) }
@@ -79,10 +99,17 @@ module Rust::Descriptive
79
99
  return percentiles.zip(result).to_h
80
100
  end
81
101
 
102
+ ##
103
+ # Returns the outliers in +data+ using Tukey's fences, with a given +k+.
104
+
82
105
  def outliers(data, k=1.5, **opts)
83
106
  outliers_according_to(data, data, k, **opts)
84
107
  end
85
108
 
109
+ ##
110
+ # Returns the outliers in +data+ using Tukey's fences, with a given +k+, with respect to different data
111
+ # distribution (+data_distribution+).
112
+
86
113
  def outliers_according_to(data, data_distribution, k=1.5, **opts)
87
114
  quantiles = Rust::Descriptive.quantile(data_distribution, [0.25, 0.75])
88
115
  q1 = quantiles[0.25]
@@ -106,3 +133,25 @@ module Rust::Descriptive
106
133
  end
107
134
  end
108
135
  end
136
+
137
+ module Rust::RBindings
138
+ def mean(series)
139
+ Rust::Descriptive.mean(series)
140
+ end
141
+
142
+ def median(series)
143
+ Rust::Descriptive.median(series)
144
+ end
145
+
146
+ def var(series)
147
+ Rust::Descriptive.variance(series)
148
+ end
149
+
150
+ def sd(series)
151
+ Rust::Descriptive.standard_deviation(series)
152
+ end
153
+
154
+ def quantile(series, percentiles = [0.0, 0.25, 0.5, 0.75, 1.0])
155
+ Rust::Descriptive.quantile(series, percentiles)
156
+ end
157
+ end