rust 0.7 → 0.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 35c41ec98f5b286ef597096152249f19825a27bc33030e85ea196df8b778d3b1
4
- data.tar.gz: 48b2e61f707ebcd05fa5f593016c8c0fb4b9d1e58751dd5deae83715583bd978
3
+ metadata.gz: 77dee9cb8c4a1e2894a8054fab8dbf140b8f6a4aed8ef38a60b41564fb5e8e69
4
+ data.tar.gz: c9bf14d2239f464cf73ffaee86bcbfe9155a323269eff1b34b7bcd1272c46d36
5
5
  SHA512:
6
- metadata.gz: b0cc1289721d52cd376e0a242c2be419ea511f03a0fdd42c4c7a1973cde24e8dfc467e9d355693f85632cccb98af6986777aa020b715db5f06aa88a63d154ea0
7
- data.tar.gz: 4c91c808773dcd04913a594cfcaa7956318908e6d590ebec1d9a04beef18986adc70a3c5e480c39bdc9f753b5edf920a1939208b8b530ccfc67124ac153a4804
6
+ metadata.gz: a648f440574e7734f979c0ec5d65bc9594202cfe88414517dcc50482e391360809ced88bbc0b825f548dfd23dd2b9dfe47b71cabbd216249d992d8a18d14717c
7
+ data.tar.gz: 1b999d94b96c05a0615ff05b3e1588c4a8e822baebba57055ae041a6fe2c7d0355d747e3c88973c9325046c59c4eff013b27336d95297c8c0e1cc06f515b2f27
data/bin/ruby-rust ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/ruby
2
+
3
+ system "RUBY_RUST_BINDING=1 irb -r \"rust\""
@@ -1,7 +1,17 @@
1
- require_relative 'rust-core'
1
+ require_relative '../core'
2
+ require 'csv'
2
3
 
3
4
  module Rust
5
+
6
+ ##
7
+ # Class that handles CSVs (both loading and saving).
8
+
4
9
  class CSV
10
+
11
+ ##
12
+ # Reads a +pattern+ of CSVs (glob-style pattern) and returns a map containing as keys the filenames of the
13
+ # loaded CSVs and as values the corresponding data-frames. Options can be specified (see #read).
14
+
5
15
  def self.read_all(pattern, **options)
6
16
  result = DataFrameHash.new
7
17
  Dir.glob(pattern).each do |filename|
@@ -10,6 +20,13 @@ module Rust
10
20
  return result
11
21
  end
12
22
 
23
+ ##
24
+ # Reads the CSV at +filename+. Options can be specified, such as:
25
+ # - headers => set to true if the first row contains the headers, false otherwise;
26
+ # - infer_numbers => if a column contains only numbers, the values are transformed into floats; true by default;
27
+ # - infer_integers => if infer_numbers is active, it distinguishes between integers and floats;
28
+ # The other options are the ones that can be used in the function R function "read.csv".
29
+
13
30
  def self.read(filename, **options)
14
31
  hash = {}
15
32
  labels = nil
@@ -45,6 +62,11 @@ module Rust
45
62
  return result
46
63
  end
47
64
 
65
+ ##
66
+ # Writes the +dataframe+ as a CSV at +filename+. Options can be specified, such as:
67
+ # - headers => set to true if the first row should contain the headers, false otherwise;
68
+ # The other options are the ones that can be used in the function R function "read.csv".
69
+
48
70
  def self.write(filename, dataframe, **options)
49
71
  raise TypeError, "Expected Rust::DataFrame" unless dataframe.is_a?(Rust::DataFrame)
50
72
 
@@ -0,0 +1,221 @@
1
+ require 'code-assertions'
2
+ require 'stringio'
3
+ require 'rinruby'
4
+
5
+ ##
6
+ # Basic module for the Rust package. It includes a series of sub-modules that provide specific features, such as
7
+ # statistical hypothesis tests, plots, and so on.
8
+
9
+ module Rust
10
+ CLIENT_MUTEX = Mutex.new
11
+ R_MUTEX = Mutex.new
12
+
13
+ R_ENGINE = RinRuby.new(echo: false)
14
+
15
+ private_constant :R_ENGINE
16
+ private_constant :R_MUTEX
17
+ private_constant :CLIENT_MUTEX
18
+
19
+ @@debugging = $RUST_DEBUG || false
20
+ @@in_client_mutex = false
21
+
22
+ ##
23
+ # Sets the debug mode. Any call to R will be written on the standard output.
24
+
25
+ def self.debug
26
+ @@debugging = true
27
+ end
28
+
29
+ ##
30
+ # Checks if the debug mode is active.
31
+
32
+ def self.debug?
33
+ return @@debugging
34
+ end
35
+
36
+ ##
37
+ # Runs the given block with a mutex. It is mandatory to run any R command with this method.
38
+
39
+ def self.exclusive
40
+ result = nil
41
+ CLIENT_MUTEX.synchronize do
42
+ @@in_client_mutex = true
43
+ result = yield
44
+ @@in_client_mutex = false
45
+ end
46
+ return result
47
+ end
48
+
49
+ ##
50
+ # Sets a variable in the R environment with a given value.
51
+ #
52
+ # Raises an error if the value can not be translated into an R object.
53
+ #
54
+ # Example: Rust['a'] = 0.
55
+
56
+ def self.[]=(variable, value)
57
+ if value.is_a?(RustDatatype)
58
+ value.load_in_r_as(variable.to_s)
59
+ elsif value.is_a?(String) || value.is_a?(Numeric) || value.is_a?(Array) || value.is_a?(::Matrix)
60
+ R_ENGINE.assign(variable, value)
61
+ else
62
+ raise "Trying to assign #{variable} with #{value.class}; expected RustDatatype, String, Numeric, or Array"
63
+ end
64
+ end
65
+
66
+ ##
67
+ # Retrieves the value of a variable from the R environment.
68
+ #
69
+ # Example: Rust['a']
70
+
71
+ def self.[](variable)
72
+ return RustDatatype.pull_variable(variable)
73
+ end
74
+
75
+ def self._eval_big(r_command, return_warnings = false)
76
+ r_command = r_command.join("\n") if r_command.is_a?(Array)
77
+
78
+ self._rexec(r_command, return_warnings) do |cmd|
79
+ result = true
80
+ instructions = cmd.lines
81
+
82
+ while instructions.size > 0
83
+ current_command = ""
84
+
85
+ while (instructions.size > 0) && (current_command.length + instructions.first.length < 10000)
86
+ current_command << instructions.shift
87
+ end
88
+
89
+ result &= R_ENGINE.eval(current_command)
90
+ end
91
+
92
+ result
93
+ end
94
+ end
95
+
96
+ def self._pull(r_command, return_warnings = false)
97
+ self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.pull(cmd) }
98
+ end
99
+
100
+ def self._eval(r_command, return_warnings = false)
101
+ self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.eval(cmd) }
102
+ end
103
+
104
+ def self._rexec(r_command, return_warnings = false)
105
+ puts "Calling _rexec with command: #{r_command}" if @@debugging
106
+ R_MUTEX.synchronize do
107
+ assert("This command must be executed in an exclusive block") { @@in_client_mutex }
108
+
109
+ result = nil
110
+ begin
111
+ $stdout = StringIO.new
112
+ if return_warnings
113
+ R_ENGINE.echo(true, true)
114
+ else
115
+ R_ENGINE.echo(false, false)
116
+ end
117
+ result = yield(r_command)
118
+ ensure
119
+ R_ENGINE.echo(false, false)
120
+ warnings = $stdout.string
121
+ $stdout = STDOUT
122
+ end
123
+
124
+ if return_warnings
125
+ puts " Got #{warnings.size} warnings, with result #{result.inspect[0...100]}" if @@debugging
126
+ return result, warnings.lines.map { |w| w.strip.chomp }
127
+ else
128
+ puts " Result: #{result.inspect[0...100]}" if @@debugging
129
+ return result
130
+ end
131
+ end
132
+ end
133
+
134
+ ##
135
+ # Checks if the given +name+ library can be used. Returns true if it is available, false otherwise.
136
+
137
+ def self.check_library(name)
138
+ self.exclusive do
139
+ result, _ = self._pull("require(\"#{name}\", character.only = TRUE)", true)
140
+ return result
141
+ end
142
+ end
143
+
144
+ ##
145
+ # Loads the given +name+ library.
146
+
147
+ def self.load_library(name)
148
+ self.exclusive do
149
+ self._eval("library(\"#{name}\", character.only = TRUE)")
150
+ end
151
+
152
+ return nil
153
+ end
154
+
155
+ ##
156
+ # Installs the given +name+ library and its dependencies.
157
+
158
+ def self.install_library(name)
159
+ self.exclusive do
160
+ self._eval("install.packages(\"#{name}\", dependencies = TRUE)")
161
+ end
162
+
163
+ return nil
164
+ end
165
+
166
+ ##
167
+ # Installs the +library+ library if it is not available and loads it.
168
+
169
+ def self.prerequisite(library)
170
+ self.install_library(library) unless self.check_library(library)
171
+ self.load_library(library)
172
+ end
173
+
174
+ ##
175
+ # Ask for help on a given +mod+.
176
+
177
+ def self.help!(mod = nil)
178
+ unless mod
179
+ puts "You have the following modules:"
180
+ Rust.constants.map { |c| Rust.const_get(c) }.select { |c| c.class == Module }.each do |mod|
181
+ puts "\t- #{mod}"
182
+ end
183
+ puts "Run \"help! {module}\" for more detailed information about the module"
184
+ else
185
+ if mod.methods.include?(:help!)
186
+ mod.help!
187
+ else
188
+ puts "Sorry, no help available for #{mod}"
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ ##
195
+ # Module that contains methods that allow to call R functions faster. Such methods have names resembling the ones
196
+ # available in R (e.g., cor, wilcox_test).
197
+
198
+ module Rust::RBindings
199
+ def data_frame(*args)
200
+ Rust::DataFrame.new(*args)
201
+ end
202
+ end
203
+
204
+ module Rust::TestCases
205
+ def self.sample_dataframe(columns, size=100)
206
+ result = Rust::DataFrame.new(columns)
207
+ size.times do |i|
208
+ result << columns.map { |c| yield i, c }
209
+ end
210
+ return result
211
+ end
212
+ end
213
+
214
+ ##
215
+ # Shortcut for including the RBinding module
216
+
217
+ def bind_r!
218
+ include Rust::RBindings
219
+ end
220
+
221
+ bind_r! if ENV['RUBY_RUST_BINDING'] == '1'
@@ -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