rust 0.7 → 0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/ruby-rust +3 -0
- data/lib/{rust-csv.rb → rust/core/csv.rb} +2 -1
- data/lib/rust/core/rust.rb +157 -0
- data/lib/rust/core/types/all.rb +4 -0
- data/lib/{rust-core.rb → rust/core/types/dataframe.rb} +17 -335
- data/lib/rust/core/types/datatype.rb +161 -0
- data/lib/rust/core/types/factor.rb +131 -0
- data/lib/rust/core/types/language.rb +166 -0
- data/lib/rust/core/types/list.rb +81 -0
- data/lib/rust/core/types/matrix.rb +132 -0
- data/lib/rust/core/types/s4class.rb +59 -0
- data/lib/rust/core/types/utils.rb +109 -0
- data/lib/rust/core.rb +7 -0
- data/lib/rust/models/all.rb +4 -0
- data/lib/rust/models/anova.rb +60 -0
- data/lib/rust/models/regression.rb +205 -0
- data/lib/rust/plots/all.rb +4 -0
- data/lib/rust/plots/basic-plots.rb +111 -0
- data/lib/{rust-plots.rb → rust/plots/core.rb} +1 -169
- data/lib/rust/plots/distribution-plots.rb +62 -0
- data/lib/rust/stats/all.rb +4 -0
- data/lib/{rust-basics.rb → rust/stats/correlation.rb} +2 -2
- data/lib/{rust-descriptive.rb → rust/stats/descriptive.rb} +24 -4
- data/lib/{rust-effsize.rb → rust/stats/effsize.rb} +7 -13
- data/lib/{rust-probabilities.rb → rust/stats/probabilities.rb} +1 -1
- data/lib/{rust-tests.rb → rust/stats/tests.rb} +84 -90
- data/lib/rust.rb +4 -9
- metadata +31 -13
- data/lib/rust-calls.rb +0 -80
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aaa404db11033ff42b529516ae4a3f3e252bdddf7677d082847ee06625144f8e
|
4
|
+
data.tar.gz: f72ebc2c95385b87a445f3fb8de3e517579b002e0606209903acd2327616befd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 00567c9b6216f7e9dc1a4135dbea263eecae2178273851c023980233531729313e15147e1bec8e9521df2d4fee15e2c4c8bf9bd4a0e2d1475f1d383339a17c21
|
7
|
+
data.tar.gz: 89800fff95be559e6f6bbbc05b6b5f5b52b7d59c54c61cd76ef679876ce5de0c08b405d88eadf0b254c95306ad98f38120e5960a92ce8358fca19ed6cc5c181d
|
data/bin/ruby-rust
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'code-assertions'
|
2
|
+
require 'stringio'
|
3
|
+
require 'rinruby'
|
4
|
+
|
5
|
+
module Rust
|
6
|
+
CLIENT_MUTEX = Mutex.new
|
7
|
+
R_MUTEX = Mutex.new
|
8
|
+
|
9
|
+
R_ENGINE = RinRuby.new(echo: false)
|
10
|
+
|
11
|
+
private_constant :R_ENGINE
|
12
|
+
private_constant :R_MUTEX
|
13
|
+
private_constant :CLIENT_MUTEX
|
14
|
+
|
15
|
+
@@debugging = $RUST_DEBUG || false
|
16
|
+
@@in_client_mutex = false
|
17
|
+
|
18
|
+
def self.debug
|
19
|
+
@@debugging = true
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.debug?
|
23
|
+
return @@debugging
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.exclusive
|
27
|
+
result = nil
|
28
|
+
CLIENT_MUTEX.synchronize do
|
29
|
+
@@in_client_mutex = true
|
30
|
+
result = yield
|
31
|
+
@@in_client_mutex = false
|
32
|
+
end
|
33
|
+
return result
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.[]=(variable, value)
|
37
|
+
if value.is_a?(RustDatatype)
|
38
|
+
value.load_in_r_as(variable.to_s)
|
39
|
+
elsif value.is_a?(String) || value.is_a?(Numeric) || value.is_a?(Array) || value.is_a?(::Matrix)
|
40
|
+
R_ENGINE.assign(variable, value)
|
41
|
+
else
|
42
|
+
raise "Trying to assign #{variable} with #{value.class}; expected RustDatatype, String, Numeric, or Array"
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.[](variable)
|
48
|
+
return RustDatatype.pull_variable(variable)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self._eval_big(r_command, return_warnings = false)
|
52
|
+
r_command = r_command.join("\n") if r_command.is_a?(Array)
|
53
|
+
|
54
|
+
self._rexec(r_command, return_warnings) do |cmd|
|
55
|
+
result = true
|
56
|
+
instructions = cmd.lines
|
57
|
+
|
58
|
+
while instructions.size > 0
|
59
|
+
current_command = ""
|
60
|
+
|
61
|
+
while (instructions.size > 0) && (current_command.length + instructions.first.length < 10000)
|
62
|
+
current_command << instructions.shift
|
63
|
+
end
|
64
|
+
|
65
|
+
result &= R_ENGINE.eval(current_command)
|
66
|
+
end
|
67
|
+
|
68
|
+
result
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self._pull(r_command, return_warnings = false)
|
73
|
+
self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.pull(cmd) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def self._eval(r_command, return_warnings = false)
|
77
|
+
self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.eval(cmd) }
|
78
|
+
end
|
79
|
+
|
80
|
+
def self._rexec(r_command, return_warnings = false)
|
81
|
+
puts "Calling _rexec with command: #{r_command}" if @@debugging
|
82
|
+
R_MUTEX.synchronize do
|
83
|
+
assert("This command must be executed in an exclusive block") { @@in_client_mutex }
|
84
|
+
|
85
|
+
result = nil
|
86
|
+
begin
|
87
|
+
$stdout = StringIO.new
|
88
|
+
if return_warnings
|
89
|
+
R_ENGINE.echo(true, true)
|
90
|
+
else
|
91
|
+
R_ENGINE.echo(false, false)
|
92
|
+
end
|
93
|
+
result = yield(r_command)
|
94
|
+
ensure
|
95
|
+
R_ENGINE.echo(false, false)
|
96
|
+
warnings = $stdout.string
|
97
|
+
$stdout = STDOUT
|
98
|
+
end
|
99
|
+
|
100
|
+
if return_warnings
|
101
|
+
puts " Got #{warnings.size} warnings, with result #{result.inspect[0...100]}" if @@debugging
|
102
|
+
return result, warnings.lines.map { |w| w.strip.chomp }
|
103
|
+
else
|
104
|
+
puts " Result: #{result.inspect[0...100]}" if @@debugging
|
105
|
+
return result
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.check_library(name)
|
111
|
+
self.exclusive do
|
112
|
+
result, _ = self._pull("require(\"#{name}\", character.only = TRUE)", true)
|
113
|
+
return result
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.load_library(name)
|
118
|
+
self.exclusive do
|
119
|
+
self._eval("library(\"#{name}\", character.only = TRUE)")
|
120
|
+
end
|
121
|
+
|
122
|
+
return nil
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.install_library(name)
|
126
|
+
self.exclusive do
|
127
|
+
self._eval("install.packages(\"#{name}\", dependencies = TRUE)")
|
128
|
+
end
|
129
|
+
|
130
|
+
return nil
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.prerequisite(library)
|
134
|
+
self.install_library(library) unless self.check_library(library)
|
135
|
+
self.load_library(library)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
module Rust::RBindings
|
140
|
+
def data_frame(*args)
|
141
|
+
Rust::DataFrame.new(*args)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
module Rust::TestCases
|
146
|
+
def self.sample_dataframe(columns, size=100)
|
147
|
+
result = Rust::DataFrame.new(columns)
|
148
|
+
size.times do |i|
|
149
|
+
result << columns.map { |c| yield i, c }
|
150
|
+
end
|
151
|
+
return result
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def bind_r!
|
156
|
+
include Rust::RBindings
|
157
|
+
end
|
@@ -1,123 +1,20 @@
|
|
1
|
-
|
2
|
-
require 'stringio'
|
3
|
-
require 'rinruby'
|
4
|
-
require 'csv'
|
1
|
+
require_relative 'datatype'
|
5
2
|
|
6
3
|
module Rust
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
R_ENGINE = RinRuby.new(echo: false)
|
11
|
-
|
12
|
-
private_constant :R_ENGINE
|
13
|
-
private_constant :R_MUTEX
|
14
|
-
private_constant :CLIENT_MUTEX
|
15
|
-
|
16
|
-
@@debugging = false
|
17
|
-
@@in_client_mutex = false
|
18
|
-
|
19
|
-
def self.debug
|
20
|
-
@@debugging = true
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.exclusive
|
24
|
-
result = nil
|
25
|
-
CLIENT_MUTEX.synchronize do
|
26
|
-
@@in_client_mutex = true
|
27
|
-
result = yield
|
28
|
-
@@in_client_mutex = false
|
29
|
-
end
|
30
|
-
return result
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.[]=(variable, value)
|
34
|
-
if value.is_a?(RustDatatype)
|
35
|
-
value.load_in_r_as(variable.to_s)
|
36
|
-
elsif value.is_a?(String) || value.is_a?(Numeric) || value.is_a?(Array)
|
37
|
-
R_ENGINE.assign(variable, value)
|
38
|
-
else
|
39
|
-
raise "Given #{value.class}, expected RustDatatype, String, Numeric, or Array"
|
4
|
+
class DataFrame < RustDatatype
|
5
|
+
def self.can_pull?(type, klass)
|
6
|
+
return [klass].flatten.include?("data.frame")
|
40
7
|
end
|
41
8
|
|
42
|
-
|
43
|
-
|
44
|
-
def self.[](variable, type=RustDatatype)
|
45
|
-
return type.pull_variable(variable)
|
46
|
-
end
|
47
|
-
|
48
|
-
def self._eval_big(r_command, return_warnings = false)
|
49
|
-
r_command = r_command.join("\n") if r_command.is_a?(Array)
|
50
|
-
|
51
|
-
self._rexec(r_command, return_warnings) do |cmd|
|
52
|
-
result = true
|
53
|
-
instructions = cmd.lines
|
54
|
-
|
55
|
-
while instructions.size > 0
|
56
|
-
current_command = ""
|
57
|
-
|
58
|
-
while (instructions.size > 0) && (current_command.length + instructions.first.length < 10000)
|
59
|
-
current_command << instructions.shift
|
60
|
-
end
|
61
|
-
|
62
|
-
result &= R_ENGINE.eval(current_command)
|
63
|
-
end
|
64
|
-
|
65
|
-
result
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def self._pull(r_command, return_warnings = false)
|
70
|
-
self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.pull(cmd) }
|
71
|
-
end
|
72
|
-
|
73
|
-
def self._eval(r_command, return_warnings = false)
|
74
|
-
self._rexec(r_command, return_warnings) { |cmd| R_ENGINE.eval(cmd) }
|
75
|
-
end
|
76
|
-
|
77
|
-
def self._rexec(r_command, return_warnings = false)
|
78
|
-
puts "Calling _rexec with command: #{r_command}" if @@debugging
|
79
|
-
R_MUTEX.synchronize do
|
80
|
-
assert("This command must be executed in an exclusive block") { @@in_client_mutex }
|
81
|
-
|
82
|
-
result = nil
|
83
|
-
begin
|
84
|
-
$stdout = StringIO.new
|
85
|
-
if return_warnings
|
86
|
-
R_ENGINE.echo(true, true)
|
87
|
-
else
|
88
|
-
R_ENGINE.echo(false, false)
|
89
|
-
end
|
90
|
-
result = yield(r_command)
|
91
|
-
ensure
|
92
|
-
R_ENGINE.echo(false, false)
|
93
|
-
warnings = $stdout.string
|
94
|
-
$stdout = STDOUT
|
95
|
-
end
|
96
|
-
|
97
|
-
if return_warnings
|
98
|
-
return result, warnings.lines.map { |w| w.strip.chomp }
|
99
|
-
else
|
100
|
-
return result
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
class RustDatatype
|
106
|
-
def self.pull_variable(variable)
|
107
|
-
return Rust._pull(variable)
|
9
|
+
def self.pull_priority
|
10
|
+
1
|
108
11
|
end
|
109
12
|
|
110
|
-
def
|
111
|
-
raise "Not implemented"
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
class DataFrame < RustDatatype
|
116
|
-
def self.pull_variable(variable)
|
13
|
+
def self.pull_variable(variable, type, klass)
|
117
14
|
hash = {}
|
118
|
-
colnames = Rust
|
15
|
+
colnames = Rust["colnames(#{variable})"]
|
119
16
|
colnames.each do |col|
|
120
|
-
hash[col] = Rust
|
17
|
+
hash[col] = Rust["#{variable}$\"#{col}\""]
|
121
18
|
end
|
122
19
|
return DataFrame.new(hash)
|
123
20
|
end
|
@@ -373,6 +270,14 @@ module Rust
|
|
373
270
|
row_index += 1
|
374
271
|
end
|
375
272
|
|
273
|
+
self.column_names.each do |name|
|
274
|
+
column = self.column(name)
|
275
|
+
|
276
|
+
if column.is_a?(Factor)
|
277
|
+
command << "#{variable_name}[,#{name.to_R}] <- factor(#{variable_name}[,#{name.to_R}], labels=#{column.levels.to_R})"
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
376
281
|
Rust._eval_big(command)
|
377
282
|
end
|
378
283
|
|
@@ -586,82 +491,6 @@ module Rust
|
|
586
491
|
end
|
587
492
|
end
|
588
493
|
|
589
|
-
class Matrix < RustDatatype
|
590
|
-
def self.pull_variable(variable)
|
591
|
-
return Rust._pull(variable)
|
592
|
-
end
|
593
|
-
|
594
|
-
def initialize(data)
|
595
|
-
if data.flatten.size == 0
|
596
|
-
raise "Empty matrices are not allowed"
|
597
|
-
else
|
598
|
-
raise TypeError, "Expected array of array" unless data.is_a?(Array) && data[0].is_a?(Array)
|
599
|
-
raise TypeError, "Only numeric matrices are supported" unless data.all? { |row| row.all? { |e| e.is_a?(Numeric) } }
|
600
|
-
raise "All the rows must have the same size" unless data.map { |row| row.size }.uniq.size == 1
|
601
|
-
@data = data.clone
|
602
|
-
end
|
603
|
-
end
|
604
|
-
|
605
|
-
def [](i, j)
|
606
|
-
return @data[i][j]
|
607
|
-
end
|
608
|
-
|
609
|
-
def rows
|
610
|
-
@data.size
|
611
|
-
end
|
612
|
-
|
613
|
-
def cols
|
614
|
-
@data[0].size
|
615
|
-
end
|
616
|
-
|
617
|
-
def []=(i, j, value)
|
618
|
-
raise "Wrong i" unless i.between?(0, @data.size - 1)
|
619
|
-
raise "Wrong j" unless j.between?(0, @data[0].size - 1)
|
620
|
-
@data[i][j] = value
|
621
|
-
end
|
622
|
-
|
623
|
-
def load_in_r_as(variable_name)
|
624
|
-
Rust._eval("#{variable_name} <- matrix(c(#{@data.flatten.join(",")}), nrow=#{self.rows}, ncol=#{self.cols}, byrow=T)")
|
625
|
-
end
|
626
|
-
end
|
627
|
-
|
628
|
-
class Sequence < RustDatatype
|
629
|
-
attr_reader :min
|
630
|
-
attr_reader :max
|
631
|
-
|
632
|
-
def initialize(min, max, step=1)
|
633
|
-
@min = min
|
634
|
-
@max = max
|
635
|
-
@step = step
|
636
|
-
end
|
637
|
-
|
638
|
-
def step(step)
|
639
|
-
@step = step
|
640
|
-
end
|
641
|
-
|
642
|
-
def each
|
643
|
-
(@min..@max).step(@step) do |v|
|
644
|
-
yield v
|
645
|
-
end
|
646
|
-
end
|
647
|
-
|
648
|
-
def to_a
|
649
|
-
result = []
|
650
|
-
self.each do |v|
|
651
|
-
result << v
|
652
|
-
end
|
653
|
-
return result
|
654
|
-
end
|
655
|
-
|
656
|
-
def to_R
|
657
|
-
"seq(from=#@min, to=#@max, by=#@step)"
|
658
|
-
end
|
659
|
-
|
660
|
-
def load_in_r_as(variable_name)
|
661
|
-
Rust._eval("#{variable_name} <- #{self.to_R}")
|
662
|
-
end
|
663
|
-
end
|
664
|
-
|
665
494
|
class DataFrameArray < Array
|
666
495
|
def bind_all
|
667
496
|
return nil if self.size == 0
|
@@ -689,151 +518,4 @@ module Rust
|
|
689
518
|
return result
|
690
519
|
end
|
691
520
|
end
|
692
|
-
|
693
|
-
class MathArray < Array
|
694
|
-
def -(other)
|
695
|
-
raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
|
696
|
-
raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
|
697
|
-
|
698
|
-
result = self.clone
|
699
|
-
other = [other] * self.size if other.is_a?(Numeric)
|
700
|
-
for i in 0...self.size
|
701
|
-
result[i] -= other[i]
|
702
|
-
end
|
703
|
-
|
704
|
-
return result
|
705
|
-
end
|
706
|
-
|
707
|
-
def *(other)
|
708
|
-
raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
|
709
|
-
raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
|
710
|
-
|
711
|
-
result = self.clone
|
712
|
-
other = [other] * self.size if other.is_a?(Numeric)
|
713
|
-
for i in 0...self.size
|
714
|
-
result[i] *= other[i]
|
715
|
-
end
|
716
|
-
|
717
|
-
return result
|
718
|
-
end
|
719
|
-
|
720
|
-
def +(other)
|
721
|
-
raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
|
722
|
-
raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
|
723
|
-
|
724
|
-
result = self.clone
|
725
|
-
other = [other] * self.size if other.is_a?(Numeric)
|
726
|
-
for i in 0...self.size
|
727
|
-
result[i] += other[i]
|
728
|
-
end
|
729
|
-
|
730
|
-
return result
|
731
|
-
end
|
732
|
-
|
733
|
-
def /(other) #To recover the syntax highlighting but in Kate: /
|
734
|
-
raise ArgumentError, "Expected array or numeric" if !other.is_a?(::Array) && !other.is_a?(Numeric)
|
735
|
-
raise ArgumentError, "The two arrays must have the same size" if other.is_a?(::Array) && self.size != other.size
|
736
|
-
|
737
|
-
result = self.clone
|
738
|
-
other = [other] * self.size if other.is_a?(Numeric)
|
739
|
-
for i in 0...self.size
|
740
|
-
result[i] /= other[i]
|
741
|
-
end
|
742
|
-
|
743
|
-
return result
|
744
|
-
end
|
745
|
-
|
746
|
-
def **(other)
|
747
|
-
raise ArgumentError, "Expected numeric" if !other.is_a?(Numeric)
|
748
|
-
|
749
|
-
result = self.clone
|
750
|
-
for i in 0...self.size
|
751
|
-
result[i] = result[i] ** other
|
752
|
-
end
|
753
|
-
|
754
|
-
return result
|
755
|
-
end
|
756
|
-
end
|
757
|
-
end
|
758
|
-
|
759
|
-
class TrueClass
|
760
|
-
def to_R
|
761
|
-
"TRUE"
|
762
|
-
end
|
763
|
-
end
|
764
|
-
|
765
|
-
class FalseClass
|
766
|
-
def to_R
|
767
|
-
"FALSE"
|
768
|
-
end
|
769
|
-
end
|
770
|
-
|
771
|
-
class Object
|
772
|
-
def to_R
|
773
|
-
raise TypeError, "Unsupported type for #{self.class}"
|
774
|
-
end
|
775
|
-
end
|
776
|
-
|
777
|
-
class NilClass
|
778
|
-
def to_R
|
779
|
-
return "NULL"
|
780
|
-
end
|
781
|
-
end
|
782
|
-
|
783
|
-
class Numeric
|
784
|
-
def to_R
|
785
|
-
self.inspect
|
786
|
-
end
|
787
|
-
end
|
788
|
-
|
789
|
-
class Float
|
790
|
-
def to_R
|
791
|
-
return self.nan? ? "NA" : super
|
792
|
-
end
|
793
|
-
end
|
794
|
-
|
795
|
-
class Array
|
796
|
-
def to_R
|
797
|
-
return "c(#{self.map { |e| e.to_R }.join(",")})"
|
798
|
-
end
|
799
|
-
|
800
|
-
def distribution
|
801
|
-
result = {}
|
802
|
-
self.each do |value|
|
803
|
-
result[value] = result[value].to_i + 1
|
804
|
-
end
|
805
|
-
return result
|
806
|
-
end
|
807
|
-
end
|
808
|
-
|
809
|
-
class String
|
810
|
-
def to_R
|
811
|
-
return self.inspect
|
812
|
-
end
|
813
|
-
end
|
814
|
-
|
815
|
-
class Range
|
816
|
-
def to_R
|
817
|
-
[range.min, range.max].to_R
|
818
|
-
end
|
819
|
-
end
|
820
|
-
|
821
|
-
module Rust::RBindings
|
822
|
-
def data_frame(*args)
|
823
|
-
Rust::DataFrame.new(*args)
|
824
|
-
end
|
825
|
-
end
|
826
|
-
|
827
|
-
module Rust::TestCases
|
828
|
-
def self.sample_dataframe(columns, size=100)
|
829
|
-
result = Rust::DataFrame.new(columns)
|
830
|
-
size.times do |i|
|
831
|
-
result << columns.map { |c| yield i, c }
|
832
|
-
end
|
833
|
-
return result
|
834
|
-
end
|
835
|
-
end
|
836
|
-
|
837
|
-
def bind_r!
|
838
|
-
include Rust::RBindings
|
839
521
|
end
|