alexgutteridge-rsruby 0.5

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.
@@ -0,0 +1,107 @@
1
+ require 'rsruby'
2
+ require 'rsruby/erobj'
3
+
4
+ #== Synopsis
5
+ #
6
+ #This is an extended ERObj class inspired by the example given in the RPy
7
+ #manual used for R data frames.
8
+ #As with ERObj, methods caught by method_missing are converted into attribute
9
+ #calls on the R dataframe it represents. The rows and columns methods give
10
+ #access to the column and row names.
11
+ #
12
+ #== Usage
13
+ #
14
+ #See examples/dataframe.rb[link:files/examples/dataframe_rb.html] for
15
+ #examples of usage.
16
+ #
17
+ #--
18
+ #== Author
19
+ #Alex Gutteridge
20
+ #
21
+ #== Copyright
22
+ #Copyright (C) 2006 Alex Gutteridge
23
+ #
24
+ # The Original Code is the RPy python module.
25
+ #
26
+ # The Initial Developer of the Original Code is Walter Moreira.
27
+ # Portions created by the Initial Developer are Copyright (C) 2002
28
+ # the Initial Developer. All Rights Reserved.
29
+ #
30
+ # Contributor(s):
31
+ # Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
32
+ #
33
+ #This library is free software; you can redistribute it and/or
34
+ #modify it under the terms of the GNU Lesser General Public
35
+ #License as published by the Free Software Foundation; either
36
+ #version 2.1 of the License, or (at your option) any later version.
37
+ #
38
+ #This library is distributed in the hope that it will be useful,
39
+ #but WITHOUT ANY WARRANTY; without even the implied warranty of
40
+ #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41
+ #Lesser General Public License for more details.
42
+ #
43
+ #You should have received a copy of the GNU Lesser General Public
44
+ #License along with this library; if not, write to the Free Software
45
+ #Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
46
+ #++
47
+
48
+ class DataFrame < ERObj
49
+
50
+ #Returns an array of the row names used in the R data frame.
51
+ def rows
52
+ return @r.attr(@robj, 'row.names')
53
+ end
54
+
55
+ #Returns an array of the column names used in the R data frame.
56
+ def columns
57
+ cols = @r.colnames(@robj)
58
+ cols = [cols] unless cols.kind_of?(Array)
59
+ return cols
60
+ end
61
+
62
+ #def[](col)
63
+ # return @r['$'].call(@robj,col.to_s)
64
+ #end
65
+
66
+ #Needs to work for named and numbered columns
67
+ def[](row,col)
68
+ if col.kind_of?(Integer) and !(columns.include?(col))
69
+ col = columns[col]
70
+ end
71
+ return @r['$'].call(@robj,col.to_s)[row]
72
+ end
73
+
74
+ def[]=(row,col,val)
75
+ #How to set a value in this dataframe?
76
+ @r.assign("rsrubytemp",@robj)
77
+
78
+ ### VERY HACKY - This relies on val having the same
79
+ #string representation in R and Ruby. An assign based
80
+ #solution with proper conversion of val would be much
81
+ #better
82
+ @r.eval_R("rsrubytemp[#{row+1},#{col+1}] <- #{val}")
83
+ #
84
+ #@r.assign("rsrubytemp[#{row+1},#{col+1}]",val)
85
+
86
+ @robj = @r.eval_R('get("rsrubytemp")')
87
+
88
+ return @r['$'].call(@robj,columns[col].to_s)[row]
89
+ end
90
+
91
+ def method_missing(attr)
92
+ attr = attr.to_s
93
+ mode = RSRuby.get_default_mode
94
+ RSRuby.set_default_mode(RSRuby::BASIC_CONVERSION)
95
+ column_names = @r.colnames(@robj)
96
+ if attr == column_names or column_names.include?(attr)
97
+ RSRuby.set_default_mode(mode)
98
+ return @r['$'].call(@robj,attr.to_s)
99
+ end
100
+
101
+ #? Not sure what here...
102
+ RSRuby.set_default_mode(mode)
103
+ return super(attr)
104
+
105
+ end
106
+
107
+ end
@@ -0,0 +1,105 @@
1
+ require 'rsruby'
2
+
3
+ #== Synopsis
4
+ #
5
+ #This is an extended RObj class inspired by the example given in the RPy
6
+ #manual. Methods caught by method_missing are converted into attribute calls
7
+ #on the R object it represents. Also to_s is redefined to print exactly the
8
+ #representation used in R.
9
+ #
10
+ #== Usage
11
+ #
12
+ #See examples/erobj.rb[link:files/examples/erobj_rb.html] for examples of
13
+ #usage.
14
+ #
15
+ #--
16
+ # == Author
17
+ # Alex Gutteridge
18
+ #
19
+ # == Copyright
20
+ #Copyright (C) 2006 Alex Gutteridge
21
+ #
22
+ # The Original Code is the RPy python module.
23
+ #
24
+ # The Initial Developer of the Original Code is Walter Moreira.
25
+ # Portions created by the Initial Developer are Copyright (C) 2002
26
+ # the Initial Developer. All Rights Reserved.
27
+ #
28
+ # Contributor(s):
29
+ # Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
30
+ #
31
+ #This library is free software; you can redistribute it and/or
32
+ #modify it under the terms of the GNU Lesser General Public
33
+ #License as published by the Free Software Foundation; either
34
+ #version 2.1 of the License, or (at your option) any later version.
35
+ #
36
+ #This library is distributed in the hope that it will be useful,
37
+ #but WITHOUT ANY WARRANTY; without even the implied warranty of
38
+ #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39
+ #Lesser General Public License for more details.
40
+ #
41
+ #You should have received a copy of the GNU Lesser General Public
42
+ #License along with this library; if not, write to the Free Software
43
+ #Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
44
+ #++
45
+
46
+ class ERObj
47
+
48
+ @@x = 1
49
+
50
+ #The ERObj is intialised by passing it an RObj instance which it then stores
51
+ def initialize(robj)
52
+ @robj = robj
53
+ @r = RSRuby.instance
54
+ end
55
+
56
+ #Returns the storred RObj.
57
+ def as_r
58
+ @robj.as_r
59
+ end
60
+
61
+ #Returns the Ruby representation of the object according to the basic
62
+ #conversion mode.
63
+ def to_ruby
64
+ @robj.to_ruby(RSRuby::BASIC_CONVERSION)
65
+ end
66
+
67
+ #Calls the storred RObj.
68
+ def lcall(args)
69
+ @robj.lcall(args)
70
+ end
71
+
72
+ #Outputs the string representation provided by R.
73
+ def to_s
74
+
75
+ @@x += 1
76
+
77
+ mode = RSRuby.get_default_mode
78
+ RSRuby.set_default_mode(RSRuby::NO_CONVERSION)
79
+ a = @r.textConnection("tmpobj#{@@x}",'w')
80
+
81
+ RSRuby.set_default_mode(RSRuby::VECTOR_CONVERSION)
82
+ @r.sink(:file => a, :type => 'output')
83
+ @r.print_(@robj)
84
+ @r.sink.call()
85
+ @r.close_connection(a)
86
+
87
+ str = @r["tmpobj#{@@x}"].join("\n")
88
+
89
+ RSRuby.set_default_mode(mode)
90
+
91
+ return str
92
+
93
+ end
94
+
95
+ #Methods caught by method_missing are converted into attribute calls on
96
+ #the R object it represents.
97
+ def method_missing(attr)
98
+ mode = RSRuby.get_default_mode
99
+ RSRuby.set_default_mode(RSRuby::BASIC_CONVERSION)
100
+ e = @r['$'].call(@robj,attr.to_s)
101
+ RSRuby.set_default_mode(mode)
102
+ return e
103
+ end
104
+
105
+ end
@@ -0,0 +1,67 @@
1
+ #== Synopsis
2
+ #
3
+ #This class represents a reference to an object in the R interpreter. It
4
+ #also holds a conversion mode used if the RObj represents a callable function.
5
+ #RObj objects can be passed to R functions called from Ruby and are the
6
+ #default return type if RSRuby cannot convert the returned results of an R
7
+ #function.
8
+ #
9
+ #--
10
+ # == Author
11
+ # Alex Gutteridge
12
+ #
13
+ # == Copyright
14
+ #Copyright (C) 2006 Alex Gutteridge
15
+ #
16
+ #This library is free software; you can redistribute it and/or
17
+ #modify it under the terms of the GNU Lesser General Public
18
+ #License as published by the Free Software Foundation; either
19
+ #version 2.1 of the License, or (at your option) any later version.
20
+ #
21
+ #This library is distributed in the hope that it will be useful,
22
+ #but WITHOUT ANY WARRANTY; without even the implied warranty of
23
+ #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24
+ #Lesser General Public License for more details.
25
+ #
26
+ #You should have received a copy of the GNU Lesser General Public
27
+ #License along with this library; if not, write to the Free Software
28
+ #Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29
+ #++
30
+
31
+ class RObj
32
+
33
+ attr_accessor :conversion, :wrap
34
+
35
+ def as_r
36
+ self
37
+ end
38
+
39
+ #Attempts to call the RObj with the arguments given. Returns the result
40
+ #of calling the R object. Only use this method if the RObj represents an
41
+ #R function.
42
+ def call(*args)
43
+ if @wrap
44
+ e = RSRuby.get_default_mode
45
+ RSRuby.set_default_mode(@wrap)
46
+ ret = self.lcall(RSRuby.convert_args_to_lcall(args))
47
+ RSRuby.set_default_mode(e)
48
+ else
49
+ ret = self.lcall(RSRuby.convert_args_to_lcall(args))
50
+ end
51
+ return ret
52
+ end
53
+
54
+ #Sets the conversion mode for this RObj (only relevant if the RObj
55
+ #represents a function). See the constants in RSRuby for valid modes.
56
+ #Returns the current conversion mode if called with no argument.
57
+ def autoconvert(m=false)
58
+ if m
59
+ raise ArgumentError if m < -1 or m > RSRuby::TOP_CONVERSION
60
+ @conversion = m
61
+ end
62
+ @conversion
63
+ end
64
+
65
+ end
66
+
67
+
data/test/table.txt ADDED
@@ -0,0 +1,4 @@
1
+ A B C D
2
+ 'X1' 4.0 5 '6'
3
+ 'X2' 7.0 8 '9'
4
+ 'X3' 6.0 2 'Foo'
data/test/tc_array.rb ADDED
@@ -0,0 +1,59 @@
1
+ require 'test/unit'
2
+ require 'rsruby'
3
+
4
+ class TestArray < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @r = RSRuby.instance
8
+ #@r.gctorture(:on => false)
9
+ @ruby_AoA = [[[0,6,12,18],[2,8,14,20],[4,10,16,22]],
10
+ [[1,7,13,19],[3,9,15,21],[5,11,17,23]]]
11
+
12
+ RSRuby.set_default_mode(RSRuby::NO_DEFAULT)
13
+ @r.array.autoconvert(RSRuby::NO_CONVERSION)
14
+ @r_array = @r.array({ :data => (0..24).to_a,
15
+ :dim => [2,3,4]})
16
+ @r.array.autoconvert(RSRuby::BASIC_CONVERSION)
17
+ end
18
+
19
+ def test_boolean
20
+ assert_equal [true,false], @r.c(true,false)
21
+ end
22
+
23
+ def test_convert_to_ruby
24
+ assert_equal(@ruby_AoA,@r_array.to_ruby)
25
+ end
26
+
27
+ #I suspect this only works in RPy with Numeric?
28
+ def test_convert_to_R
29
+ @r.list.autoconvert(RSRuby::NO_CONVERSION)
30
+ @r['[['].autoconvert(RSRuby::NO_CONVERSION)
31
+ o = @r['[['].call(@r.list(@ruby_AoA),1)
32
+ @r['[['].autoconvert(RSRuby::BASIC_CONVERSION)
33
+ #assert_equal(@r.all_equal(o,@r_array),true)
34
+ end
35
+
36
+ def test_dimensions
37
+ assert_equal(@r.dim(@r_array),[@ruby_AoA.length,
38
+ @ruby_AoA[0].length,
39
+ @ruby_AoA[0][0].length])
40
+ end
41
+
42
+ def test_elements
43
+ assert_equal(@ruby_AoA[0][0][0],@r['[['].call(@r_array, 1,1,1))
44
+ assert_equal(@ruby_AoA[1][1][1],@r['[['].call(@r_array, 2,2,2))
45
+ end
46
+
47
+ def test_ruby_out_of_bounds
48
+ assert_raise NoMethodError do
49
+ @ruby_AoA[5][5][5]
50
+ end
51
+ end
52
+
53
+ def test_R_out_of_bounds
54
+ assert_raise RException do
55
+ @r['[['].call(@r_array, 5,5,5)
56
+ end
57
+ end
58
+
59
+ end
@@ -0,0 +1,30 @@
1
+ require 'test/unit'
2
+ require 'rsruby'
3
+
4
+ class TestBoolean < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @r = RSRuby.instance
8
+ RSRuby.set_default_mode(RSRuby::NO_DEFAULT)
9
+ @r.c.autoconvert(RSRuby::BASIC_CONVERSION)
10
+ end
11
+
12
+ def test_true
13
+ assert_block "r.TRUE not working" do
14
+ (@r.typeof(@r.FALSE) == 'logical' and
15
+ @r.as_logical(@r.TRUE))
16
+ end
17
+ end
18
+
19
+ def test_false
20
+ assert_block "r.FALSE not working" do
21
+ (@r.typeof(@r.FALSE) == 'logical' and not
22
+ @r.as_logical(@r.FALSE))
23
+ end
24
+ end
25
+
26
+ def test_boolean_array
27
+ assert_equal([true,false,true,false],@r.c(true,false,true,false))
28
+ end
29
+
30
+ end
@@ -0,0 +1,22 @@
1
+ require 'test/unit'
2
+ require 'rsruby'
3
+
4
+ class TestCleanup < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @r = RSRuby.instance
8
+ end
9
+
10
+ def test_shutdown
11
+ #@r.eval_R("shutdown_test=10")
12
+ #@r.shutdown
13
+ #assert_raise(RException){ @r.eval_R("shutdown_test") }
14
+ end
15
+
16
+ def test_crash
17
+ #Signal.trap('BUS','EXIT')
18
+ #Signal.trap('BUS',proc{ puts 'hi there'; exit!})
19
+ #@r.crash
20
+ end
21
+
22
+ end
data/test/tc_eval.rb ADDED
@@ -0,0 +1,21 @@
1
+ require 'test/unit'
2
+ require 'rsruby'
3
+
4
+ class TestEval < Test::Unit::TestCase
5
+
6
+ def setup
7
+ @r = RSRuby.instance
8
+ @r.proc_table = {}
9
+ @r.class_table = {}
10
+ end
11
+
12
+ def test_eval_R
13
+ #Test integer, Float, String and Boolean return values
14
+ assert_equal(@r.eval_R("sum(1,2,3)"),6)
15
+ assert_equal(@r.eval_R("sum(1.5,2.5,3.5)"),7.5)
16
+ assert_equal(@r.eval_R("eval('R')"),"R")
17
+ assert_equal(@r.eval_R("is(1,'numeric')"),true)
18
+ assert_equal(@r.eval_R("is(1,'madeup')"),false)
19
+ end
20
+
21
+ end
@@ -0,0 +1,43 @@
1
+ require 'test/unit'
2
+ require 'rsruby'
3
+
4
+ class TestNewCases < Test::Unit::TestCase
5
+ @@test_dir = File.expand_path File.dirname(__FILE__)
6
+
7
+ def test_erobj
8
+
9
+ require 'rsruby/erobj'
10
+ r = RSRuby.instance
11
+ r.proc_table[lambda{|x| true}] = lambda{|x| ERObj.new(x)}
12
+ RSRuby.set_default_mode(RSRuby::PROC_CONVERSION)
13
+
14
+ f = r.c(1,2,3)
15
+ assert_equal('[1] 1 2 3',f.to_s)
16
+ assert_equal([1,2,3],f.to_ruby)
17
+ assert_instance_of(RObj,f.as_r)
18
+
19
+ end
20
+
21
+ def test_dataframe
22
+
23
+ require 'rsruby/dataframe'
24
+ r = RSRuby.instance
25
+ r.class_table['data.frame'] = lambda{|x| DataFrame.new(x)}
26
+ RSRuby.set_default_mode(RSRuby::CLASS_CONVERSION)
27
+ table = r.read_table(@@test_dir+"/table.txt",:header=>true)
28
+ assert_instance_of(DataFrame,table)
29
+
30
+ assert_equal(['A','B','C','D'],table.columns)
31
+ assert_equal([1,2,3],table.rows)
32
+
33
+ #assert_equal(['X1','X2','X3'],table['A'])
34
+ assert_equal('X2',table[1,'A'])
35
+ assert_equal('X2',table[1,0])
36
+
37
+ assert_equal(7,table[1,1])
38
+ table[1,1] = 5
39
+ assert_equal(5,table[1,1])
40
+
41
+ end
42
+
43
+ end