galaaz 0.4.2 → 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +25 -0
- data/Rakefile +8 -0
- data/bin/gknit +9 -5
- data/bin/gstudio +4 -2
- data/bin/gstudio.rb +32 -2
- data/blogs/dev/dev.html +219 -34
- data/blogs/dev/dev.md +26 -26
- data/blogs/dev/dev_files/figure-html/bubble-1.png +0 -0
- data/blogs/dev/dev_files/figure-html/diverging_bar.png +0 -0
- data/blogs/dplyr/dplyr.rb +63 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -26
- data/blogs/galaaz_ggplot/galaaz_ggplot.aux +16 -17
- data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.tex +65 -31
- data/blogs/oh_my/not_so.rb +2342 -0
- data/blogs/oh_my/oh_my.Rmd +493 -0
- data/blogs/oh_my/oh_my.html +680 -0
- data/blogs/oh_my/oh_my.md +597 -0
- data/blogs/oh_my/old.Rmd +2100 -0
- data/blogs/ruby_plot/figures/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/figures/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/figures/final_box_plot.png +0 -0
- data/blogs/ruby_plot/figures/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/figures/violin_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot.Rmd +147 -122
- data/blogs/ruby_plot/ruby_plot.Rmd_external_figs +662 -0
- data/blogs/ruby_plot/ruby_plot.html +49 -54
- data/blogs/ruby_plot/ruby_plot.md +147 -122
- data/blogs/ruby_plot/ruby_plot.pdf +0 -0
- data/blogs/ruby_plot/ruby_plot.tex +776 -157
- data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.svg +57 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.svg +106 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.svg +110 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.svg +174 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.svg +236 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.svg +296 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.svg +236 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.svg +218 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.svg +128 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.svg +150 -0
- data/examples/islr/ch2.spec.rb +21 -18
- data/examples/islr/ch3_boston.rb +14 -5
- data/examples/islr/ch3_multiple_regression.rb +2 -3
- data/examples/islr/ch6.spec.rb +1 -1
- data/examples/islr/x_y_rnorm.jpg +0 -0
- data/lib/R_interface/r.rb +14 -10
- data/lib/R_interface/r_libs.R +9 -0
- data/lib/R_interface/r_methods.rb +77 -6
- data/lib/R_interface/{expression.rb → r_module_s.rb} +13 -14
- data/lib/R_interface/rbinary_operators.rb +58 -71
- data/lib/R_interface/rdata_frame.rb +2 -1
- data/lib/R_interface/rdevices.R +4 -0
- data/lib/R_interface/rdevices.rb +1 -1
- data/lib/R_interface/renvironment.rb +34 -1
- data/lib/R_interface/rexpression.rb +108 -2
- data/lib/R_interface/rindexed_object.rb +3 -1
- data/lib/R_interface/rlanguage.rb +18 -2
- data/lib/R_interface/rmatrix.rb +14 -0
- data/lib/R_interface/rmd_indexed_object.rb +5 -1
- data/lib/R_interface/robject.rb +61 -23
- data/lib/R_interface/rsupport.rb +111 -53
- data/lib/R_interface/rsymbol.rb +6 -5
- data/lib/R_interface/ruby_extensions.rb +130 -4
- data/lib/R_interface/runary_operators.rb +35 -3
- data/lib/R_interface/rvector.rb +1 -0
- data/lib/galaaz.rb +0 -2
- data/lib/gknit/knitr_engine.rb +58 -4
- data/lib/gknit/ruby_engine.rb +5 -6
- data/lib/util/exec_ruby.rb +55 -9
- data/specs/all.rb +13 -3
- data/specs/figures/dose_len.png +0 -0
- data/specs/r_dataframe.spec.rb +49 -26
- data/specs/r_environment.spec.rb +140 -0
- data/specs/r_eval.spec.rb +0 -15
- data/specs/r_formula.spec.rb +232 -0
- data/specs/r_function.spec.rb +7 -8
- data/specs/r_list.spec.rb +4 -0
- data/specs/r_list_apply.spec.rb +11 -11
- data/specs/r_matrix.spec.rb +3 -3
- data/specs/{r_plots.spec.rb~ → r_nse.spec.rb} +29 -6
- data/specs/r_vector_creation.spec.rb +6 -0
- data/specs/r_vector_object.spec.rb +2 -2
- data/specs/r_vector_operators.spec.rb +3 -3
- data/specs/r_vector_subsetting.spec.rb +4 -4
- data/specs/ruby_expression.spec.rb +324 -0
- data/specs/tmp.rb +12 -524
- data/sty/galaaz.sty +71 -0
- data/version.rb +1 -1
- metadata +31 -41
- data/bin/gknit2~ +0 -6
- data/bin/ogk~ +0 -4
- data/bin/prepareR.rb~ +0 -1
- data/blogs/dev/dev.Rmd~ +0 -104
- data/blogs/galaaz_ggplot/galaaz_ggplot.dvi +0 -0
- data/blogs/galaaz_ggplot/midwest_external_png~ +0 -1
- data/blogs/gknit/gknit.Rmd~ +0 -184
- data/blogs/gknit/gknit.Rnd~ +0 -17
- data/blogs/gknit/model.rb~ +0 -46
- data/blogs/ruby_plot/ruby_plot.Rmd~ +0 -215
- data/examples/islr/Figure.jpg +0 -0
- data/examples/misc/moneyball.rb~ +0 -16
- data/examples/misc/subsetting.rb~ +0 -372
- data/lib/R/eng_ruby.R~ +0 -63
- data/lib/R_interface/capture_plot.rb~ +0 -23
- data/lib/R_interface/r.rb~ +0 -121
- data/lib/R_interface/rdevices.rb~ +0 -27
- data/lib/gknit.rb~ +0 -26
- data/lib/gknit/knitr_engine.rb~ +0 -102
- data/lib/gknit/ruby_engine.rb~ +0 -72
- data/lib/util/inline_file.rb~ +0 -23
- data/r_requires/knitr.rb~ +0 -4
- data/specs/r_language.spec.rb +0 -157
data/specs/r_function.spec.rb
CHANGED
@@ -55,8 +55,8 @@ describe R do
|
|
55
55
|
f = R.outer(@x, @y,
|
56
56
|
lambda { |x, y|
|
57
57
|
R.cos(y) / (x**2 + 1)})
|
58
|
-
expect(f[1, 1]
|
59
|
-
expect(f[7, 6]
|
58
|
+
expect(f[1, 1].all__equal -0.091999668).to eq true
|
59
|
+
expect(f[7, 6].all__equal 0.448193475).to eq true
|
60
60
|
end
|
61
61
|
|
62
62
|
it "should accept a Method as parameter" do
|
@@ -70,10 +70,9 @@ describe R do
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
-
f = R.outer(@x, @y, Calculation.method(:func))
|
74
|
-
expect(f[1, 1]
|
75
|
-
expect(f[7, 6]
|
76
|
-
|
73
|
+
f = R.outer(@x, @y, Calculation.method(:func))
|
74
|
+
expect(f[1, 1].all__equal -0.091999668).to eq true
|
75
|
+
expect(f[7, 6].all__equal 0.448193475).to eq true
|
77
76
|
end
|
78
77
|
|
79
78
|
it "should accept Procs in Expressions" do
|
@@ -85,8 +84,8 @@ describe R do
|
|
85
84
|
|
86
85
|
# now lets evaluate f in the scope of df, where :x and :y are defined
|
87
86
|
res = f.eval(df)
|
88
|
-
expect(res[1, 1]
|
89
|
-
expect(res[10,
|
87
|
+
expect(res[1, 1].all__equal -0.091999668).to eq true
|
88
|
+
expect(res[10, 9].all__equal -0.0704758347).to eq true
|
90
89
|
end
|
91
90
|
|
92
91
|
it "Should be able to 'eval' a Proc in expression" do
|
data/specs/r_list.spec.rb
CHANGED
@@ -81,6 +81,10 @@ describe R::List do
|
|
81
81
|
expect(@l[R.c(4, 1)].identical(R.list(R.list(4, 5, 6), 1))).to eq true
|
82
82
|
end
|
83
83
|
|
84
|
+
it "should raise an exception when index dimension is wrong" do
|
85
|
+
expect { @l[4, 1] }.to raise_error(ArgumentError)
|
86
|
+
end
|
87
|
+
|
84
88
|
it "should subset with [[]] and positive integer. Returns the actual element of the list" do
|
85
89
|
# to extract an element of a list we need double square (dbk) indexing
|
86
90
|
expect(@l[[1]]).to eq 1
|
data/specs/r_list_apply.spec.rb
CHANGED
@@ -60,8 +60,8 @@ describe R::List do
|
|
60
60
|
quant = R.lapply(@x, @q)
|
61
61
|
expect(quant.a[1]).to eq 1
|
62
62
|
expect(quant.a["50,00000%"]).to eq 5.50
|
63
|
-
expect(R.all__equal(quant.beta["100
|
64
|
-
20.08553692,
|
63
|
+
expect(R.all__equal(quant.beta["100%"],
|
64
|
+
R.c('100%': 20.08553692),
|
65
65
|
tolerance: (~:".Machine").double__eps ** 0.5)).to eq true
|
66
66
|
expect(quant.logic[2]).to eq 0.0
|
67
67
|
end
|
@@ -70,28 +70,28 @@ describe R::List do
|
|
70
70
|
x = R.lapply(@x, @q, R.c(0.25, 0.50, 0.75))
|
71
71
|
expect(x.a[1]).to eq 3.25
|
72
72
|
expect(x.a["50,00000%"]).to eq 5.50
|
73
|
-
expect(R.all__equal(x.beta[
|
74
|
-
5.0536690,
|
73
|
+
expect(R.all__equal(x.beta['75%'],
|
74
|
+
R.c('75%': 5.0536690),
|
75
75
|
tolerance: (~:".Machine").double__eps ** 0.5)).to eq true
|
76
76
|
expect(x.logic[2]).to eq 0.5
|
77
77
|
end
|
78
78
|
|
79
79
|
it "should allow using sapply and quantile" do
|
80
80
|
quant = R.sapply(@x, @q)
|
81
|
-
expect
|
82
|
-
expect
|
83
|
-
expect
|
81
|
+
expect(quant.rclass).to eq 'matrix'
|
82
|
+
expect(quant[:all, 'a']).to eq R.c(1, 3.25, 5.50, 7.75, 10)
|
83
|
+
expect(quant[3, 'beta']).to eq 1
|
84
84
|
end
|
85
85
|
|
86
86
|
it "should sapply to a sequence" do
|
87
87
|
# sapply isn’t content to always return a list: it attempts to simplify
|
88
88
|
# the results into a non-list vector if possible.
|
89
89
|
i39 = R.sapply((3..9), "seq")
|
90
|
-
expect
|
91
|
-
expect
|
90
|
+
expect(i39[[1]]).to eq R.c(1, 2, 3)
|
91
|
+
expect(i39[[7]]).to eq R.c(1, 2, 3, 4, 5, 6, 7, 8, 9)
|
92
92
|
sap = R.sapply(i39, ~:fivenum)
|
93
|
-
expect
|
94
|
-
expect
|
93
|
+
expect(sap[1, 1]).to eq 1
|
94
|
+
expect(sap[5, 7]).to eq 9
|
95
95
|
end
|
96
96
|
|
97
97
|
end
|
data/specs/r_matrix.spec.rb
CHANGED
@@ -23,7 +23,7 @@
|
|
23
23
|
|
24
24
|
require 'galaaz'
|
25
25
|
|
26
|
-
describe R do
|
26
|
+
describe R::Matrix do
|
27
27
|
|
28
28
|
#----------------------------------------------------------------------------------------
|
29
29
|
context "Matrices" do
|
@@ -74,8 +74,8 @@ describe R do
|
|
74
74
|
it "should apply a function to all elements of the matrix: ex: sqrt" do
|
75
75
|
x = R.matrix(data: R.c(1, 2, 3, 4), nrow: 2, ncol: 2, byrow: true)
|
76
76
|
z = x.sqrt
|
77
|
-
expect(z[1, 2]
|
78
|
-
expect(z[2, 1]
|
77
|
+
expect(z[1, 2].all__equal(1.41421356)).to eq true
|
78
|
+
expect(z[2, 1].all__equal(1.73205080)).to eq true
|
79
79
|
end
|
80
80
|
|
81
81
|
end
|
@@ -23,15 +23,38 @@
|
|
23
23
|
|
24
24
|
require 'galaaz'
|
25
25
|
|
26
|
-
describe R
|
27
|
-
|
28
|
-
|
29
|
-
context "
|
30
|
-
|
31
|
-
it "should create a plot with ggplot" do
|
26
|
+
describe R do
|
27
|
+
|
28
|
+
#========================================================================================
|
29
|
+
context "Non-standard Evaluation" do
|
32
30
|
|
31
|
+
before(:all) do
|
32
|
+
@sample_df = R.data__frame(a: (1..5), b: (5..1), c: R.c(5, 3, 1, 4, 1))
|
33
33
|
end
|
34
34
|
|
35
|
+
it "should allow functions to receive objects and conditions for evaluation" do
|
36
|
+
|
37
|
+
def subset(df, condition)
|
38
|
+
# evaluate the condition in the scope of the dataframe
|
39
|
+
r = R.eval(condition, df)
|
40
|
+
df[r, :all]
|
41
|
+
end
|
42
|
+
|
43
|
+
puts subset(@sample_df, :a >= 4)
|
44
|
+
|
45
|
+
y = 4
|
46
|
+
x = 4
|
47
|
+
condition = 4
|
48
|
+
condition_call = 4
|
49
|
+
|
50
|
+
puts subset(@sample_df, :a == 4)
|
51
|
+
puts subset(@sample_df, :a == y)
|
52
|
+
puts subset(@sample_df, :a == condition)
|
53
|
+
puts subset(@sample_df, :a == condition_call)
|
54
|
+
end
|
55
|
+
|
35
56
|
end
|
36
57
|
|
37
58
|
end
|
59
|
+
|
60
|
+
|
@@ -35,6 +35,12 @@ describe R::Vector do
|
|
35
35
|
expect(log_vect.mode).to eq "logical"
|
36
36
|
expect(log_vect.storage__mode).to eq "logical"
|
37
37
|
end
|
38
|
+
|
39
|
+
it "should create a vector from a scalar" do
|
40
|
+
vec = R.c(1)
|
41
|
+
expect(vec.length).to eq 1
|
42
|
+
expect(vec.class).to eq R::Vector
|
43
|
+
end
|
38
44
|
|
39
45
|
it "should create integer Vectors" do
|
40
46
|
# in R, numbers are converted to double. To get an int one needs to add L after the
|
@@ -67,12 +67,12 @@ describe R::Vector do
|
|
67
67
|
expect(@vect.rclass).to eq "newClass"
|
68
68
|
end
|
69
69
|
|
70
|
-
it "
|
70
|
+
it "will copy vectors and changes will not be seen" do
|
71
71
|
# pending "Need to implement new function for this"
|
72
72
|
# set names
|
73
73
|
@vect.names = R.c("a", "b", "c", "d", "e", "f")
|
74
74
|
@vect.names[2] = "hello"
|
75
|
-
expect(@vect.names[2]).to eq "
|
75
|
+
expect(@vect.names[2]).to eq R.c("b")
|
76
76
|
end
|
77
77
|
|
78
78
|
end
|
@@ -73,7 +73,7 @@ describe R::Vector do
|
|
73
73
|
res = 10 - @vec1
|
74
74
|
expect(res == R.c(7, 4.3, 0, -1)).to eq true
|
75
75
|
res = 10 / @vec1
|
76
|
-
expect(res
|
76
|
+
expect(res.all__equal R.c(3.333333333, 1.754385964, 1, 0.833333333)).to eq true
|
77
77
|
end
|
78
78
|
|
79
79
|
end
|
@@ -86,9 +86,9 @@ describe R::Vector do
|
|
86
86
|
vec2 = R.c(1, 2)
|
87
87
|
vec3 = R.c(0, 2)
|
88
88
|
|
89
|
-
expect((vec1
|
89
|
+
expect((vec1.eql vec2).all__equal(R.c(true, true))).to eq true
|
90
90
|
expect((vec1 != vec2).all__equal(R.c(false, false))).to eq true
|
91
|
-
expect((vec1
|
91
|
+
expect((vec1.eql vec3).all__equal(R.c(false, true))).to eq true
|
92
92
|
end
|
93
93
|
|
94
94
|
it "should check vectors for <, <=, >, >=" do
|
@@ -82,7 +82,7 @@ describe R::Vector do
|
|
82
82
|
# element
|
83
83
|
@vect.each_with_index do |elmt, i|
|
84
84
|
expect(elmt.typeof == 'integer').to eq true
|
85
|
-
expect
|
85
|
+
expect(elmt).to eq i
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
@@ -97,7 +97,7 @@ describe R::Vector do
|
|
97
97
|
it "should subset with 'each_with_index(:native)' getting a Ruby element" do
|
98
98
|
# when using the :native keyword, indexing starts at 0
|
99
99
|
@vect.each_with_index(:native) do |elmt, i|
|
100
|
-
expect
|
100
|
+
expect(elmt).to eq i + 1
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
@@ -108,7 +108,7 @@ describe R::Vector do
|
|
108
108
|
|
109
109
|
it "should retrieve values the same way as single square brackets" do
|
110
110
|
vect = R.c(2.1, 4.2, 3.3, 5.4)
|
111
|
-
expect
|
111
|
+
expect(vect[[1]]).to eq 2.1
|
112
112
|
end
|
113
113
|
|
114
114
|
end
|
@@ -123,7 +123,7 @@ describe R::Vector do
|
|
123
123
|
it "should subset assign with integer" do
|
124
124
|
expect(@vect[2]).to eq 2
|
125
125
|
@vect[2] = 1000
|
126
|
-
expect
|
126
|
+
expect(@vect[2]).to eq 1000
|
127
127
|
end
|
128
128
|
|
129
129
|
it "should subset assign to the elements given by another vector" do
|
@@ -0,0 +1,324 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
##########################################################################################
|
4
|
+
# @author Rodrigo Botafogo
|
5
|
+
#
|
6
|
+
# Copyright © 2018 Rodrigo Botafogo. All Rights Reserved. Permission to use, copy, modify,
|
7
|
+
# and distribute this software and its documentation, without fee and without a signed
|
8
|
+
# licensing agreement, is hereby granted, provided that the above copyright notice, this
|
9
|
+
# paragraph and the following two paragraphs appear in all copies, modifications, and
|
10
|
+
# distributions.
|
11
|
+
#
|
12
|
+
# IN NO EVENT SHALL RODRIGO BOTAFOGO BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
|
13
|
+
# INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF
|
14
|
+
# THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF RODRIGO BOTAFOGO HAS BEEN ADVISED OF THE
|
15
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
16
|
+
#
|
17
|
+
# RODRIGO BOTAFOGO SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
18
|
+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
19
|
+
# SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS".
|
20
|
+
# RODRIGO BOTAFOGO HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
|
21
|
+
# OR MODIFICATIONS.
|
22
|
+
##########################################################################################
|
23
|
+
|
24
|
+
require 'galaaz'
|
25
|
+
|
26
|
+
#========================================================================================
|
27
|
+
# class Expression in the R module extends Ruby's symbols, so that they can be used in
|
28
|
+
# forming expressions of the form ':x + :y' or more complex than that. Those
|
29
|
+
# expressions will then be converted to R expressions when necessary.
|
30
|
+
#========================================================================================
|
31
|
+
|
32
|
+
describe Symbol do
|
33
|
+
|
34
|
+
#========================================================================================
|
35
|
+
context "Working with Ruby expressions" do
|
36
|
+
|
37
|
+
before(:each) do
|
38
|
+
R.len = 10
|
39
|
+
R.sd = 20
|
40
|
+
R.vec = R.c(1, 2, 3, 4)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should convert a Ruby symbol into an R symbol with unary '+'" do
|
44
|
+
exp = +:len
|
45
|
+
expect(exp.class).to eq R::RSymbol
|
46
|
+
expect(exp.rclass).to eq "integer"
|
47
|
+
expect(exp.typeof).to eq "integer"
|
48
|
+
expect(exp.eval).to eq 10
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should convert a Ruby symbol into an R symbol with 'expr'" do
|
52
|
+
exp = R.expr(:len)
|
53
|
+
expect(exp.class).to eq R::RSymbol
|
54
|
+
expect(exp.rclass).to eq "integer"
|
55
|
+
expect(exp.typeof).to eq "integer"
|
56
|
+
expect(exp.eval).to eq 10
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should convert 'true' and 'false' to TRUE and FALSE in R" do
|
60
|
+
e = R.expr(true)
|
61
|
+
expect(e).to eq R.c(true)
|
62
|
+
e = R.expr(false)
|
63
|
+
expect(e).to eq R.c(false)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should allow binary operations with 'expressions'" do
|
67
|
+
e1 = +:len
|
68
|
+
e2 = e1 + 5
|
69
|
+
expect(e2.eval).to eq R.c(15)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should convert binary operations with Symbols to 'expressions'" do
|
73
|
+
e1 = :len + :sd
|
74
|
+
expect(e1.to_s).to eq "len + sd"
|
75
|
+
expect(e1.class).to eq R::Language
|
76
|
+
expect(e1.rclass).to eq "integer"
|
77
|
+
expect(e1.eval).to eq 30
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should convert longer Ruby expressions to 'expression'" do
|
81
|
+
e1 = :len + :sd + 5
|
82
|
+
expect(e1.to_s).to eq "len + sd + 5L"
|
83
|
+
expect(e1.class).to eq R::Language
|
84
|
+
expect(e1.rclass).to eq "integer"
|
85
|
+
expect(e1.eval).to eq 35
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should operate with all comparison operators" do
|
89
|
+
df = R.data__frame(a: (1..5), b: (5..1), c: R.c(5, 3, 1, 4, 1))
|
90
|
+
|
91
|
+
e = :a > :b
|
92
|
+
expect(e.to_s).to eq "a > b"
|
93
|
+
expect(e.eval(df)).to eq R.c(false, false, false, true, true)
|
94
|
+
|
95
|
+
e = :a.gt :b
|
96
|
+
expect(e.to_s).to eq "a > b"
|
97
|
+
expect(e.eval(df)).to eq R.c(false, false, false, true, true)
|
98
|
+
|
99
|
+
e = :a >= :b
|
100
|
+
expect(e.to_s).to eq "a >= b"
|
101
|
+
expect(e.eval(df)).to eq R.c(false, false, true, true, true)
|
102
|
+
|
103
|
+
e = :a.ge :b
|
104
|
+
expect(e.to_s).to eq "a >= b"
|
105
|
+
expect(e.eval(df)).to eq R.c(false, false, true, true, true)
|
106
|
+
|
107
|
+
e = :a < :b
|
108
|
+
expect(e.to_s).to eq "a < b"
|
109
|
+
expect(e.eval(df)).to eq R.c(true, true, false, false, false)
|
110
|
+
|
111
|
+
e = :a.lt :b
|
112
|
+
expect(e.to_s).to eq "a < b"
|
113
|
+
expect(e.eval(df)).to eq R.c(true, true, false, false, false)
|
114
|
+
|
115
|
+
e = :a <= :b
|
116
|
+
expect(e.to_s).to eq "a <= b"
|
117
|
+
expect(e.eval(df)).to eq R.c(true, true, true, false, false)
|
118
|
+
|
119
|
+
e = :a.le :b
|
120
|
+
expect(e.to_s).to eq "a <= b"
|
121
|
+
expect(e.eval(df)).to eq R.c(true, true, true, false, false)
|
122
|
+
|
123
|
+
e = :a != :b
|
124
|
+
expect(e.to_s).to eq "a != b"
|
125
|
+
expect(e.eval(df)).to eq R.c(true, true, false, true, true)
|
126
|
+
|
127
|
+
e = :a.ne :b
|
128
|
+
expect(e.to_s).to eq "a != b"
|
129
|
+
expect(e.eval(df)).to eq R.c(true, true, false, true, true)
|
130
|
+
|
131
|
+
e = :a.eq :b
|
132
|
+
expect(e.to_s).to eq "a == b"
|
133
|
+
expect(e.eval(df)).to eq R.c(false, false, true, false, false)
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should inline r objects in 'expressions'" do
|
138
|
+
e1 = :len + :sd + 5 + R.c(1, 2, 3, 4)
|
139
|
+
expect(e1.to_s).to eq "len + sd + 5L + 1:4"
|
140
|
+
expect(e1.class).to eq R::Language
|
141
|
+
expect(e1.rclass).to eq "integer"
|
142
|
+
expect(e1.eval).to eq R.c(36, 37, 38, 39)
|
143
|
+
expect(e1.eval).not_to eq R.c(35, 37, 38, 39)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should create assignment expressions with method 'assign'" do
|
147
|
+
e = :x.assign :vec * 10
|
148
|
+
expect(e.to_s).to eq "x <- vec * 10L"
|
149
|
+
expect(e.eval).to eq R.c(10, 20, 30, 40)
|
150
|
+
expect(~:x).to eq R.c(10, 20, 30, 40)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should create quoted functions with 'E'" do
|
154
|
+
exp = E.sin(:vec)
|
155
|
+
expect(exp.to_s).to eq "sin(vec)"
|
156
|
+
expect(exp.eval.
|
157
|
+
all__equal R.c(0.841470984, 0.909297426, 0.141120008, -0.756802495)).to eq true
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should require quoted expression to convert expression to string with 'as_string'" do
|
161
|
+
exp = E.expr(:len)
|
162
|
+
expect(exp.to_s).to eq "expr(len)"
|
163
|
+
expect(exp.as_string).to eq "len"
|
164
|
+
expect(exp.is__symbol).to eq true
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should be possible to check if an expression is a call" do
|
168
|
+
exp = E.expr(E.sin(:x))
|
169
|
+
expect(exp.typeof).to eq "language"
|
170
|
+
expect(exp.typeof).not_to eq "matrix"
|
171
|
+
expect(exp.is__call).to eq true
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should be able to subset a call as with lists" do
|
175
|
+
x = E.expr(E.read__table("important.csv", row__names: false))
|
176
|
+
expect(x.typeof).to eq "language"
|
177
|
+
expect(x.is__call).to eq true
|
178
|
+
expect(x[[1]].to_s).to eq "read.table"
|
179
|
+
expect(x[[2]]).to eq "important.csv"
|
180
|
+
expect(x[[3]]).to eq false
|
181
|
+
expect(x[["row.names"]]).to eq false
|
182
|
+
expect(x[["row.names"]]).not_to eq true
|
183
|
+
expect(x.length).to eq 3
|
184
|
+
# puts x.row__names # does not work yet
|
185
|
+
# puts x.call_standardise # does not work yet
|
186
|
+
# x.header = true # does not work yet
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should allow constructing calls with 'call2'" do
|
190
|
+
e = R.call2("mean", x: E.expr(:x), na__rm: true)
|
191
|
+
expect(e.to_s).to eq "mean(x = x, na.rm = TRUE)"
|
192
|
+
|
193
|
+
#> mean(x = x, na.rm = TRUE)
|
194
|
+
# e = call2(E.base::mean, x: E.expr(:x), na__rm: TRUE) # does not work yet
|
195
|
+
# puts e
|
196
|
+
#> base::mean(x = x, na.rm = TRUE)
|
197
|
+
|
198
|
+
e = R.call2("<-", E.expr(:x), 10)
|
199
|
+
e.eval
|
200
|
+
expect(~:x).to eq 10
|
201
|
+
end
|
202
|
+
|
203
|
+
it "should allow executing a function with 'exec'" do
|
204
|
+
val = R.exec("mean", x: (1..10), na__rm: true, trim: 0.1)
|
205
|
+
expect(val).to eq 5.5
|
206
|
+
|
207
|
+
# using ruby arrays and * in place of !!!(list)
|
208
|
+
args = [x: (1..10), na__rm: true, trim: 0.1]
|
209
|
+
expect(R.exec("mean", *args)).to eq 5.5
|
210
|
+
|
211
|
+
# using ruby arrays and parameter in the function call. Note however
|
212
|
+
# that according to Ruby's rule, the array must come before the hash
|
213
|
+
# so R.exec("mean", x: (1..10), *params) is a syntax error
|
214
|
+
params = [na__rm: true, trim: 0.1]
|
215
|
+
expect(R.exec("mean", *params, x: (1..10))).to eq 5.5
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
#========================================================================================
|
221
|
+
context "Expressions inside functions" do
|
222
|
+
|
223
|
+
it "should allow the use of expression in quoted functions" do
|
224
|
+
x = y = R.seq(-~:pi, ~:pi, length: 10)
|
225
|
+
df = R.data__frame(x: x, y: y)
|
226
|
+
|
227
|
+
# quote the outer function
|
228
|
+
e = E.outer(:x, :y, lambda { |x, y| R.cos(y) / (1 + x**2) })
|
229
|
+
|
230
|
+
# evaluate the expression in the scope of a data frame
|
231
|
+
res = e.eval(df)
|
232
|
+
expect(res.rclass).to eq "matrix"
|
233
|
+
expect(res[1, 1].all__equal -0.091999668).to eq true
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should be able to pass an expression to a 'subset'" do
|
237
|
+
df = R.data__frame(a: (1..5), b: (5..1), c: R.c(5, 3, 1, 4, 1))
|
238
|
+
|
239
|
+
sub = R.subset(df, (:a.eq :b))
|
240
|
+
expect(sub.rclass).to eq "data.frame"
|
241
|
+
expect(sub[1, 1]).to eq 3
|
242
|
+
|
243
|
+
sub = R.subset(df, :a >= 4)
|
244
|
+
expect(sub.nrow).to eq 2
|
245
|
+
expect(sub.ncol).to eq 3
|
246
|
+
expect(sub[1, 1]).to eq 4
|
247
|
+
expect(sub[1, 3]).to eq 4
|
248
|
+
expect(sub[2, 2]).to eq 1
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
252
|
+
|
253
|
+
#========================================================================================
|
254
|
+
context "Evaluate data in the context of the ruby instance" do
|
255
|
+
|
256
|
+
before(:each) do
|
257
|
+
@df = R.data__frame(a: (1..5), b: (5..1), c: R.c(5, 3, 1, 4, 1))
|
258
|
+
end
|
259
|
+
|
260
|
+
it "should access columns of the data frame by name" do
|
261
|
+
# Note that we use {a} and not {:a}. In the context of the @df
|
262
|
+
# object 'a' is a call to the method that returns column 'a'
|
263
|
+
expect(@df.instance_eval {a}).to eq R.c(1, 2, 3, 4, 5)
|
264
|
+
expect(@df.instance_eval {b}).to eq R.c(5, 4, 3, 2, 1)
|
265
|
+
expect(@df.instance_eval {c}).to eq R.c(5, 3, 1, 4, 1)
|
266
|
+
end
|
267
|
+
|
268
|
+
it "should evaluate the expression in the given instance" do
|
269
|
+
# Ruby way of evaluation code in the scope of an object.
|
270
|
+
val = @df.instance_eval {a.eql 4}
|
271
|
+
expect(val).to eq R.c(false, false, false, true, false)
|
272
|
+
|
273
|
+
val = @df.instance_eval {a >= 3}
|
274
|
+
expect(val).to eq R.c(false, false, true, true, true)
|
275
|
+
|
276
|
+
val = @df.instance_eval {a.eql b}
|
277
|
+
expect(val).to eq R.c(false, false, true, false, false)
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
#========================================================================================
|
284
|
+
context "Tidyverse evaluation" do
|
285
|
+
|
286
|
+
it "should allow passing expressions to ggplot" do
|
287
|
+
require 'ggplot'
|
288
|
+
|
289
|
+
# df is a Ruby symbol and ToothGrowth is an R dataframe. But at this point
|
290
|
+
# there is no relationship between the two
|
291
|
+
df = :ToothGrowth
|
292
|
+
|
293
|
+
# we now call a method on a Ruby symbol. This will try to identify if this
|
294
|
+
# method exists in the R dataframe. This is one of the columns of the R
|
295
|
+
# dataframe, so 'dose' is now an R expression
|
296
|
+
dose = df.dose
|
297
|
+
expect(dose.to_s).to eq "ToothGrowth[[\"dose\"]]"
|
298
|
+
|
299
|
+
# dose.assign is an R expression, equivalent to 'ToothGrowth[["dose"]] <-'
|
300
|
+
# an the whole expression becomes:
|
301
|
+
# 'ToothGrowth[["dose"]] <- as.factor(ToothGrowth[["dose"]])'
|
302
|
+
dose.assign dose.as__factor
|
303
|
+
|
304
|
+
df2 = R.data__frame(
|
305
|
+
R.aggregate(df.len, by: R.list(dose), FUN: :mean),
|
306
|
+
R.aggregate(df.len, by: R.list(dose), FUN: :sd)[2]
|
307
|
+
)
|
308
|
+
|
309
|
+
df2.names = R.c("dose", "len", "sd")
|
310
|
+
|
311
|
+
# pass the expressions ':len - :sd' and ':len + :sd' to the aes function
|
312
|
+
f = df2.ggplot(E.aes(x: :dose, y: :len,
|
313
|
+
ymin: :len - :sd,
|
314
|
+
ymax: :len + :sd))
|
315
|
+
|
316
|
+
# create the graphics and saves it
|
317
|
+
R.png("specs/figures/dose_len.png")
|
318
|
+
puts f + R.geom_crossbar
|
319
|
+
R.dev__off
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|