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.
@@ -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