alexgutteridge-rsruby 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -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