galaaz 0.4.2 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +25 -0
  3. data/Rakefile +8 -0
  4. data/bin/gknit +9 -5
  5. data/bin/gstudio +4 -2
  6. data/bin/gstudio.rb +32 -2
  7. data/blogs/dev/dev.html +219 -34
  8. data/blogs/dev/dev.md +26 -26
  9. data/blogs/dev/dev_files/figure-html/bubble-1.png +0 -0
  10. data/blogs/dev/dev_files/figure-html/diverging_bar.png +0 -0
  11. data/blogs/dplyr/dplyr.rb +63 -0
  12. data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -26
  13. data/blogs/galaaz_ggplot/galaaz_ggplot.aux +16 -17
  14. data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
  15. data/blogs/galaaz_ggplot/galaaz_ggplot.tex +65 -31
  16. data/blogs/oh_my/not_so.rb +2342 -0
  17. data/blogs/oh_my/oh_my.Rmd +493 -0
  18. data/blogs/oh_my/oh_my.html +680 -0
  19. data/blogs/oh_my/oh_my.md +597 -0
  20. data/blogs/oh_my/old.Rmd +2100 -0
  21. data/blogs/ruby_plot/figures/facets_with_decorations.png +0 -0
  22. data/blogs/ruby_plot/figures/facets_with_jitter.png +0 -0
  23. data/blogs/ruby_plot/figures/final_box_plot.png +0 -0
  24. data/blogs/ruby_plot/figures/final_violin_plot.png +0 -0
  25. data/blogs/ruby_plot/figures/violin_with_jitter.png +0 -0
  26. data/blogs/ruby_plot/ruby_plot.Rmd +147 -122
  27. data/blogs/ruby_plot/ruby_plot.Rmd_external_figs +662 -0
  28. data/blogs/ruby_plot/ruby_plot.html +49 -54
  29. data/blogs/ruby_plot/ruby_plot.md +147 -122
  30. data/blogs/ruby_plot/ruby_plot.pdf +0 -0
  31. data/blogs/ruby_plot/ruby_plot.tex +776 -157
  32. data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.svg +57 -0
  33. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.svg +106 -0
  34. data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.svg +110 -0
  35. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.svg +174 -0
  36. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.svg +236 -0
  37. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
  38. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.svg +296 -0
  39. data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.svg +236 -0
  40. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.svg +218 -0
  41. data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.svg +128 -0
  42. data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.svg +150 -0
  43. data/examples/islr/ch2.spec.rb +21 -18
  44. data/examples/islr/ch3_boston.rb +14 -5
  45. data/examples/islr/ch3_multiple_regression.rb +2 -3
  46. data/examples/islr/ch6.spec.rb +1 -1
  47. data/examples/islr/x_y_rnorm.jpg +0 -0
  48. data/lib/R_interface/r.rb +14 -10
  49. data/lib/R_interface/r_libs.R +9 -0
  50. data/lib/R_interface/r_methods.rb +77 -6
  51. data/lib/R_interface/{expression.rb → r_module_s.rb} +13 -14
  52. data/lib/R_interface/rbinary_operators.rb +58 -71
  53. data/lib/R_interface/rdata_frame.rb +2 -1
  54. data/lib/R_interface/rdevices.R +4 -0
  55. data/lib/R_interface/rdevices.rb +1 -1
  56. data/lib/R_interface/renvironment.rb +34 -1
  57. data/lib/R_interface/rexpression.rb +108 -2
  58. data/lib/R_interface/rindexed_object.rb +3 -1
  59. data/lib/R_interface/rlanguage.rb +18 -2
  60. data/lib/R_interface/rmatrix.rb +14 -0
  61. data/lib/R_interface/rmd_indexed_object.rb +5 -1
  62. data/lib/R_interface/robject.rb +61 -23
  63. data/lib/R_interface/rsupport.rb +111 -53
  64. data/lib/R_interface/rsymbol.rb +6 -5
  65. data/lib/R_interface/ruby_extensions.rb +130 -4
  66. data/lib/R_interface/runary_operators.rb +35 -3
  67. data/lib/R_interface/rvector.rb +1 -0
  68. data/lib/galaaz.rb +0 -2
  69. data/lib/gknit/knitr_engine.rb +58 -4
  70. data/lib/gknit/ruby_engine.rb +5 -6
  71. data/lib/util/exec_ruby.rb +55 -9
  72. data/specs/all.rb +13 -3
  73. data/specs/figures/dose_len.png +0 -0
  74. data/specs/r_dataframe.spec.rb +49 -26
  75. data/specs/r_environment.spec.rb +140 -0
  76. data/specs/r_eval.spec.rb +0 -15
  77. data/specs/r_formula.spec.rb +232 -0
  78. data/specs/r_function.spec.rb +7 -8
  79. data/specs/r_list.spec.rb +4 -0
  80. data/specs/r_list_apply.spec.rb +11 -11
  81. data/specs/r_matrix.spec.rb +3 -3
  82. data/specs/{r_plots.spec.rb~ → r_nse.spec.rb} +29 -6
  83. data/specs/r_vector_creation.spec.rb +6 -0
  84. data/specs/r_vector_object.spec.rb +2 -2
  85. data/specs/r_vector_operators.spec.rb +3 -3
  86. data/specs/r_vector_subsetting.spec.rb +4 -4
  87. data/specs/ruby_expression.spec.rb +324 -0
  88. data/specs/tmp.rb +12 -524
  89. data/sty/galaaz.sty +71 -0
  90. data/version.rb +1 -1
  91. metadata +31 -41
  92. data/bin/gknit2~ +0 -6
  93. data/bin/ogk~ +0 -4
  94. data/bin/prepareR.rb~ +0 -1
  95. data/blogs/dev/dev.Rmd~ +0 -104
  96. data/blogs/galaaz_ggplot/galaaz_ggplot.dvi +0 -0
  97. data/blogs/galaaz_ggplot/midwest_external_png~ +0 -1
  98. data/blogs/gknit/gknit.Rmd~ +0 -184
  99. data/blogs/gknit/gknit.Rnd~ +0 -17
  100. data/blogs/gknit/model.rb~ +0 -46
  101. data/blogs/ruby_plot/ruby_plot.Rmd~ +0 -215
  102. data/examples/islr/Figure.jpg +0 -0
  103. data/examples/misc/moneyball.rb~ +0 -16
  104. data/examples/misc/subsetting.rb~ +0 -372
  105. data/lib/R/eng_ruby.R~ +0 -63
  106. data/lib/R_interface/capture_plot.rb~ +0 -23
  107. data/lib/R_interface/r.rb~ +0 -121
  108. data/lib/R_interface/rdevices.rb~ +0 -27
  109. data/lib/gknit.rb~ +0 -26
  110. data/lib/gknit/knitr_engine.rb~ +0 -102
  111. data/lib/gknit/ruby_engine.rb~ +0 -72
  112. data/lib/util/inline_file.rb~ +0 -23
  113. data/r_requires/knitr.rb~ +0 -4
  114. data/specs/r_language.spec.rb +0 -157
@@ -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] == -0.09199967).to eq true
59
- expect(f[7, 6] == -0.04599983).to eq true
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] == -0.09199967).to eq true
75
- expect(f[7, 6] == -0.04599983).to eq true
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] == -0.09199967).to eq true
89
- expect(res[10, 10] == -0.09199967).to eq true
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
@@ -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
@@ -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,0000%"],
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["75,00000%"],
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 quant.rclass == 'matrix'
82
- expect quant[:all, 'a'] == R.c(1, 3.25, 5.50, 7.75, 10)
83
- expect quant[3, 'beta'] == 1
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 i39[[1]] == R.c(1, 2, 3)
91
- expect i39[[7]] == R.c(1, 2, 3, 4, 5, 6, 7, 8, 9)
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 sap[1, 1] == 1
94
- expect sap[5, 7] == 9
93
+ expect(sap[1, 1]).to eq 1
94
+ expect(sap[5, 7]).to eq 9
95
95
  end
96
96
 
97
97
  end
@@ -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] == 1.73).to eq true
78
- expect(z[2, 1] == 1.41).to eq true
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::Plots do
27
-
28
- #----------------------------------------------------------------------------------------
29
- context "Create a Plot" do
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 "should allow changing an element of a vector attribute" do
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 "hello"
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 == R.c(3.3333333, 1.7543860, 1, 0.8333333)).to eq true
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 == vec2).all__equal(R.c(true, true))).to eq true
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 == vec3).all__equal(R.c(false, true))).to eq true
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 elmt == i
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 elmt == i + 1
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 vect[[1]] == 2.1
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 @vect[2] == 1000
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