rsruby 0.4.0 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/License.txt +504 -0
- data/Manifest.txt +37 -0
- data/README.txt +96 -0
- data/examples/arrayfields.rb +50 -34
- data/examples/bioc.rb +34 -98
- data/examples/dataframe.rb +34 -14
- data/examples/erobj.rb +29 -15
- data/ext/{rsruby/Converters.c → Converters.c} +50 -25
- data/ext/{rsruby/Converters.h → Converters.h} +3 -0
- data/ext/{rsruby/R_eval.c → R_eval.c} +0 -0
- data/ext/{rsruby/R_eval.h → R_eval.h} +0 -0
- data/ext/{rsruby/extconf.rb → extconf.rb} +0 -7
- data/ext/{rsruby/robj.c → robj.c} +0 -0
- data/ext/{rsruby/rsruby.c → rsruby.c} +12 -26
- data/ext/{rsruby/rsruby.h → rsruby.h} +0 -0
- data/lib/rsruby.rb +49 -125
- data/lib/rsruby/dataframe.rb +11 -6
- data/lib/rsruby/erobj.rb +18 -10
- data/lib/rsruby/robj.rb +7 -2
- data/test/table.txt +4 -0
- data/test/tc_array.rb +13 -16
- data/test/tc_boolean.rb +5 -8
- data/test/tc_cleanup.rb +11 -13
- data/test/tc_eval.rb +9 -5
- data/test/tc_extensions.rb +26 -0
- data/test/tc_io.rb +7 -10
- data/test/tc_library.rb +6 -6
- data/test/tc_modes.rb +131 -79
- data/test/tc_robj.rb +26 -29
- data/test/tc_sigint.rb +1 -1
- data/test/tc_to_r.rb +57 -60
- data/test/tc_to_ruby.rb +62 -65
- data/test/tc_vars.rb +14 -14
- data/test/test_all.rb +21 -0
- metadata +34 -40
- data/README +0 -102
data/Manifest.txt
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
History.txt
|
2
|
+
License.txt
|
3
|
+
Manifest.txt
|
4
|
+
README.txt
|
5
|
+
examples/arrayfields.rb
|
6
|
+
examples/bioc.rb
|
7
|
+
examples/dataframe.rb
|
8
|
+
examples/erobj.rb
|
9
|
+
ext/Converters.c
|
10
|
+
ext/Converters.h
|
11
|
+
ext/R_eval.c
|
12
|
+
ext/R_eval.h
|
13
|
+
ext/extconf.rb
|
14
|
+
ext/robj.c
|
15
|
+
ext/rsruby.c
|
16
|
+
ext/rsruby.h
|
17
|
+
lib/rsruby.rb
|
18
|
+
lib/rsruby/dataframe.rb
|
19
|
+
lib/rsruby/erobj.rb
|
20
|
+
lib/rsruby/robj.rb
|
21
|
+
test/table.txt
|
22
|
+
test/tc_array.rb
|
23
|
+
test/tc_boolean.rb
|
24
|
+
test/tc_cleanup.rb
|
25
|
+
test/tc_eval.rb
|
26
|
+
test/tc_extensions.rb
|
27
|
+
test/tc_init.rb
|
28
|
+
test/tc_io.rb
|
29
|
+
test/tc_library.rb
|
30
|
+
test/tc_modes.rb
|
31
|
+
test/tc_robj.rb
|
32
|
+
test/tc_sigint.rb
|
33
|
+
test/tc_to_r.rb
|
34
|
+
test/tc_to_ruby.rb
|
35
|
+
test/tc_util.rb
|
36
|
+
test/tc_vars.rb
|
37
|
+
test/test_all.rb
|
data/README.txt
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
== Introduction
|
2
|
+
|
3
|
+
RSRuby is a bridge library for Ruby giving Ruby developers access to the full R statistical programming environment. RSRuby embeds a full R interpreter inside the running Ruby script, allowing R methods to be called and data passed between the Ruby script and the R interpreter. Most data conversion is handled automatically, but user-definable conversion routines can also be written to handle any R or Ruby class.
|
4
|
+
|
5
|
+
RSRuby is a partial conversion of RPy[http://rpy.sourceforge.net/], and shares the same goals of robustness, ease of use and speed. The current version is stable and passes 90% of the RPy test suite. Some conversion and method calling semantics differ between RPy and RSRuby (largely due to the differences between Python and Ruby), but they are now largely similar in functonality.
|
6
|
+
|
7
|
+
Major things to be done in the future include proper handling of OS signals, user definable I/O functions, improved DataFrame support and inevitable bug fixes.
|
8
|
+
|
9
|
+
== Installation
|
10
|
+
|
11
|
+
A working R installation is required. R must have been built with the '--enable-R-shlib' option enabled to provide the R shared library used by RSRuby.
|
12
|
+
|
13
|
+
Ensure the R_HOME environment variable is set appropriately. E.g.:
|
14
|
+
|
15
|
+
R_HOME=/usr/lib/R (on Ubuntu Linux)
|
16
|
+
R_HOME=/Library/Frameworks/R.framework/Resources (on OS X)
|
17
|
+
|
18
|
+
An RSRuby gem is available as well as a package using setup.rb. In each case the installation requires the location of your R library to compile the extension. This is usually the same as R_HOME. If you download the setup.rb package use these incantations:
|
19
|
+
|
20
|
+
ruby setup.rb config -- --with-R-dir=$R_HOME
|
21
|
+
ruby setup.rb setup
|
22
|
+
ruby setup.rb install
|
23
|
+
|
24
|
+
Using gems it is almost the same:
|
25
|
+
|
26
|
+
gem install rsruby -- --with-R-dir=$R_HOME
|
27
|
+
|
28
|
+
If RSRuby does not compile correctly you may need to configure the path to the R library, any one of the following should be sufficient:
|
29
|
+
|
30
|
+
o Put the following line in your .bashrc (or equivalent):
|
31
|
+
|
32
|
+
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:RHOME/bin
|
33
|
+
|
34
|
+
o or, make a link to RHOME/bin/libR.so in /usr/local/lib or /usr/lib, then run 'ldconfig'.
|
35
|
+
|
36
|
+
o or, edit the file /etc/ld.so.conf, add the following line and then run 'ldconfig':
|
37
|
+
|
38
|
+
RHOME/bin
|
39
|
+
|
40
|
+
== Documentation
|
41
|
+
|
42
|
+
There are a few sources of documentation for RSRuby, though the manual should be considered the authoritative text.
|
43
|
+
|
44
|
+
Manual:: The manual[http://web.kuicr.kyoto-u.ac.jp/~alexg/rsruby/manual.pdf] has most of the comprehensive information on calling R functions and the conversion system.
|
45
|
+
Examples:: A few example scripts are included in the distribution:
|
46
|
+
* Using Arrayfields[link:files/examples/arrayfields_rb.html] instead of Hash for named lists/vectors.
|
47
|
+
* Using the Bioconductor[link:files/examples/bioc_rb.html] library.
|
48
|
+
* An example[link:files/examples/dataframe_rb.html] using the DataFrame class.
|
49
|
+
* An example[link:files/examples/erobj_rb.html] using the ERObj class.
|
50
|
+
Tests:: The test scripts also show several usage examples.
|
51
|
+
|
52
|
+
Finally, here is a very quick and simple example:
|
53
|
+
|
54
|
+
#Initialize R
|
55
|
+
require 'rsruby'
|
56
|
+
|
57
|
+
#RSRuby uses Singleton design pattern so call instance rather
|
58
|
+
#than new
|
59
|
+
r = RSRuby.instance
|
60
|
+
#Call R functions on the r object
|
61
|
+
data = r.rnorm(100)
|
62
|
+
r.plot(data)
|
63
|
+
sleep(2)
|
64
|
+
#Call with named args
|
65
|
+
r.plot({'x' => data,
|
66
|
+
'y' => data,
|
67
|
+
'xlab' => 'test',
|
68
|
+
'ylab' => 'test'})
|
69
|
+
sleep(2)
|
70
|
+
|
71
|
+
== License
|
72
|
+
|
73
|
+
Copyright (C) 2006 Alex Gutteridge
|
74
|
+
|
75
|
+
The Original Code is the RPy python module.
|
76
|
+
|
77
|
+
The Initial Developer of the Original Code is Walter Moreira.
|
78
|
+
Portions created by the Initial Developer are Copyright (C) 2002
|
79
|
+
the Initial Developer. All Rights Reserved.
|
80
|
+
|
81
|
+
Contributor(s):
|
82
|
+
Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
|
83
|
+
|
84
|
+
This library is free software; you can redistribute it and/or
|
85
|
+
modify it under the terms of the GNU Lesser General Public
|
86
|
+
License as published by the Free Software Foundation; either
|
87
|
+
version 2.1 of the License, or (at your option) any later version.
|
88
|
+
|
89
|
+
This library is distributed in the hope that it will be useful,
|
90
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
91
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
92
|
+
Lesser General Public License for more details.
|
93
|
+
|
94
|
+
You should have received a copy of the GNU Lesser General Public
|
95
|
+
License along with this library; if not, write to the Free Software
|
96
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
data/examples/arrayfields.rb
CHANGED
@@ -1,36 +1,52 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
#==Synopsis
|
2
|
+
#
|
3
|
+
#This example shows the use of custom converters to change the default
|
4
|
+
#RSRuby behaviour. Normally RSRuby converts an R list or vector with the
|
5
|
+
#name attribute to a Ruby Hash. Ruby Hashes do not conserve order however
|
6
|
+
#unlike the R datatypes.
|
7
|
+
#
|
8
|
+
#To better replicate the R behaviour, this code uses the arrayfields library
|
9
|
+
#(available as a gem) and the RSRuby Proc conversion mode to create named
|
10
|
+
#Arrays which preserve order.
|
11
|
+
#
|
12
|
+
#NB: You can run this file like a normal Ruby script. I use some post-
|
13
|
+
#processing to allow me to add the source to RDoc.
|
14
|
+
#
|
15
|
+
# require 'arrayfields'
|
16
|
+
# require 'rsruby'
|
17
|
+
#
|
18
|
+
#First we generate a Proc that will return true if we have an R object
|
19
|
+
#that has the 'names' attribute set:
|
20
|
+
#
|
21
|
+
# test_proc = lambda{|x| !(RSRuby.instance.attr(x,'names').nil?) }
|
22
|
+
#
|
23
|
+
#The next Proc takes the R object and generates a new Array with fields
|
24
|
+
#set appropriately:
|
25
|
+
#
|
26
|
+
# conv_proc = lambda{|x|
|
27
|
+
# hash = x.to_ruby
|
28
|
+
# array = []
|
29
|
+
# array.fields = RSRuby.instance.attr(x,'names')
|
30
|
+
# RSRuby.instance.attr(x,'names').each{|f| array[f] = hash[f]}
|
31
|
+
# return array
|
32
|
+
# }
|
33
|
+
#
|
34
|
+
#Next we start R, set the t.test function to use Proc conversion and
|
35
|
+
#add our Procs to the proc_table Hash.
|
36
|
+
#
|
37
|
+
# r = RSRuby.instance
|
38
|
+
# r.t_test.autoconvert(RSRuby::PROC_CONVERSION)
|
39
|
+
# r.proc_table[test_proc] = conv_proc
|
40
|
+
#
|
41
|
+
#The return values from t.test are now Arrays rather than Hashes:
|
42
|
+
#
|
43
|
+
# ttest = r.t_test([1,2,3])
|
44
|
+
# puts ttest.class
|
45
|
+
# ttest.each_pair do |field,val|
|
46
|
+
# puts "#{field} - #{val}"
|
47
|
+
# end
|
48
|
+
# puts ttest[1..3]
|
4
49
|
|
5
|
-
|
6
|
-
|
7
|
-
names = r.attr(x,'names')
|
8
|
-
if names.nil?
|
9
|
-
return false
|
10
|
-
else
|
11
|
-
return true
|
12
|
-
end
|
13
|
-
}
|
14
|
-
|
15
|
-
conv_proc = lambda{|x|
|
16
|
-
r = RSRuby.instance
|
17
|
-
names = r.attr(x,'names')
|
18
|
-
hash = x.to_ruby
|
19
|
-
array = []
|
20
|
-
array.fields = names
|
21
|
-
names.each do |field|
|
22
|
-
array[field] = hash[field]
|
23
|
-
end
|
24
|
-
return array
|
25
|
-
}
|
26
|
-
|
27
|
-
r = RSRuby.instance
|
28
|
-
r.t_test.autoconvert(RSRuby::PROC_CONVERSION)
|
29
|
-
r.proc_table[test_proc] = conv_proc
|
30
|
-
|
31
|
-
ttest = r.t_test([1,2,3])
|
32
|
-
puts ttest.class
|
33
|
-
ttest.each_pair do |field,val|
|
34
|
-
puts "#{field} - #{val}"
|
50
|
+
if __FILE__ == $0
|
51
|
+
eval(IO.read($0).gsub(/^\#\s\s/,''))
|
35
52
|
end
|
36
|
-
puts ttest[1..3]
|
data/examples/bioc.rb
CHANGED
@@ -1,99 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
RSRuby.set_default_mode(mode)
|
37
|
-
|
38
|
-
return str
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
def method_missing(attr)
|
43
|
-
mode = RSRuby.get_default_mode
|
44
|
-
RSRuby.set_default_mode(RSRuby::BASIC_CONVERSION)
|
45
|
-
e = @r['$'].call(@robj,attr.to_s)
|
46
|
-
RSRuby.set_default_mode(mode)
|
47
|
-
return e
|
48
|
-
end
|
49
|
-
|
1
|
+
#==Synopsis
|
2
|
+
#
|
3
|
+
#This example shows the use of the DataFrame class and eval_R to execute some
|
4
|
+
#Bioconductor code
|
5
|
+
#
|
6
|
+
# require 'rsruby'
|
7
|
+
# require 'dataframe'
|
8
|
+
#
|
9
|
+
# r = RSRuby.instance
|
10
|
+
#
|
11
|
+
#First we setup the class_table Hash to convert dataframes to Ruby DataFrames
|
12
|
+
#
|
13
|
+
# r.class_table['data.frame'] = lambda{|x| DataFrame.new(x)}
|
14
|
+
# RSRuby.set_default_mode(RSRuby::CLASS_CONVERSION)
|
15
|
+
#
|
16
|
+
#Then we load the Bioconductor affy library and use eval_R to run some affy
|
17
|
+
#code
|
18
|
+
#
|
19
|
+
# r.library('affy')
|
20
|
+
#
|
21
|
+
# r.eval_R("mydata <- ReadAffy()")
|
22
|
+
# r.eval_R("eset.rma <- rma(mydata)")
|
23
|
+
# r.eval_R("eset.pma <- mas5calls(mydata)")
|
24
|
+
#
|
25
|
+
#frame = r.eval_R("data.frame(exprs(eset.rma), exprs(eset.pma), se.exprs(eset.pma))")
|
26
|
+
#
|
27
|
+
# puts frame.class
|
28
|
+
# puts frame.rows.join(" ")
|
29
|
+
# puts frame.columns.join(" ")
|
30
|
+
#
|
31
|
+
# puts frame.send('COLD_12H_SHOOT_REP1.cel'.to_sym)
|
32
|
+
|
33
|
+
if __FILE__ == $0
|
34
|
+
eval(IO.read($0).gsub(/^\#\s\s/,''))
|
50
35
|
end
|
51
|
-
|
52
|
-
class DataFrame < ERObj
|
53
|
-
|
54
|
-
def rows
|
55
|
-
return @r.attr(@robj, 'row.names')
|
56
|
-
end
|
57
|
-
|
58
|
-
def columns
|
59
|
-
cols = @r.colnames(@robj)
|
60
|
-
cols = [cols] unless cols.class == 'Array'
|
61
|
-
return cols
|
62
|
-
end
|
63
|
-
|
64
|
-
def method_missing(attr)
|
65
|
-
attr = attr.to_s
|
66
|
-
mode = RSRuby.get_default_mode
|
67
|
-
RSRuby.set_default_mode(RSRuby::BASIC_CONVERSION)
|
68
|
-
column_names = @r.colnames(@robj)
|
69
|
-
if attr == column_names or column_names.include?(attr)
|
70
|
-
RSRuby.set_default_mode(mode)
|
71
|
-
return @r['$'].call(@robj,attr.to_s)
|
72
|
-
end
|
73
|
-
|
74
|
-
#? Not sure what here...
|
75
|
-
RSRuby.set_default_mode(mode)
|
76
|
-
return super(attr)
|
77
|
-
|
78
|
-
end
|
79
|
-
|
80
|
-
end
|
81
|
-
|
82
|
-
r = RSRuby.instance
|
83
|
-
|
84
|
-
r.class_table['data.frame'] = lambda{|x| DataFrame.new(x)}
|
85
|
-
|
86
|
-
r.library('affy')
|
87
|
-
|
88
|
-
r.eval_R("mydata <- ReadAffy()")
|
89
|
-
r.eval_R("eset.rma <- rma(mydata)")
|
90
|
-
r.eval_R("eset.pma <- mas5calls(mydata)")
|
91
|
-
|
92
|
-
RSRuby.set_default_mode(RSRuby::CLASS_CONVERSION)
|
93
|
-
frame = r.eval_R("data.frame(exprs(eset.rma), exprs(eset.pma), se.exprs(eset.pma))")
|
94
|
-
|
95
|
-
puts frame.class
|
96
|
-
puts frame.rows.join(" ")
|
97
|
-
puts frame.columns.join(" ")
|
98
|
-
|
99
|
-
puts frame.send('COLD_12H_SHOOT_REP1.cel'.to_sym)
|
data/examples/dataframe.rb
CHANGED
@@ -1,15 +1,35 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#==Synopsis
|
2
|
+
#
|
3
|
+
#This example shows the use of the Class conversion system to convert
|
4
|
+
#dataframes into the Ruby DataFrame class
|
5
|
+
#
|
6
|
+
# require 'rsruby'
|
7
|
+
# require 'rsruby/dataframe'
|
8
|
+
#
|
9
|
+
# r = RSRuby.instance
|
10
|
+
#
|
11
|
+
#Here we just set up a simple class table that returns a new DataFrame
|
12
|
+
#object when a dataframe is returned by R
|
13
|
+
#
|
14
|
+
# r.class_table['data.frame'] = lambda{|x| DataFrame.new(x)}
|
15
|
+
# RSRuby.set_default_mode(RSRuby::CLASS_CONVERSION)
|
16
|
+
#
|
17
|
+
#We then create a dataframe object to test the conversion
|
18
|
+
# e = r.as_data_frame(:x => {'foo' => [4,5,6], 'bar' => ['X','Y','Z']})
|
19
|
+
#
|
20
|
+
#Using some of the ERObj and DataFrame class capabilities we can access the
|
21
|
+
#dataframe data in various ways
|
22
|
+
#
|
23
|
+
# puts e
|
24
|
+
# puts e.foo.join(" ")
|
25
|
+
# puts e.bar.join(" ")
|
26
|
+
# puts e.rows.join(" ")
|
27
|
+
# puts e.columns.join(" ")
|
28
|
+
#
|
29
|
+
# puts e.baz.join(" ")
|
30
|
+
#
|
31
|
+
# puts e['foo'].join(" ")
|
3
32
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
#slight kludge here need to use this form because of the
|
8
|
-
#calling with keywords semantics are different to RPy
|
9
|
-
e = r.as_data_frame(:x => {'foo' => [4,5,6], 'bar' => ['X','Y','Z']})
|
10
|
-
|
11
|
-
puts e
|
12
|
-
puts e.foo.join(" ")
|
13
|
-
puts e.bar.join(" ")
|
14
|
-
puts e.rows.join(" ")
|
15
|
-
puts e.columns.join(" ")
|
33
|
+
if __FILE__ == $0
|
34
|
+
eval(IO.read($0).gsub(/^\#\s\s/,''))
|
35
|
+
end
|
data/examples/erobj.rb
CHANGED
@@ -1,16 +1,30 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#==Synopsis
|
2
|
+
#
|
3
|
+
#In this example we intercept the conversion system using the proc conversion
|
4
|
+
#mode. Instead of converting, every object returned by R is converted to an
|
5
|
+
#ERObj
|
6
|
+
#
|
7
|
+
# require 'rsruby'
|
8
|
+
# require 'rsruby/erobj'
|
9
|
+
#
|
10
|
+
# r = RSRuby.instance
|
11
|
+
#
|
12
|
+
#Setting the proc table up with a Proc which always returns true serves to
|
13
|
+
#intercept the RSRuby conversion system. The conversion system is bypassed
|
14
|
+
#into the second Proc
|
15
|
+
#
|
16
|
+
# r.proc_table[lambda{|x| true}] = lambda{|x| ERObj.new(x)}
|
17
|
+
# RSRuby.set_default_mode(RSRuby::PROC_CONVERSION)
|
18
|
+
#
|
19
|
+
# e = r.t_test([1,2,3,4,5,6])
|
20
|
+
#
|
21
|
+
#One feature of ERObj is that they output the same string representation
|
22
|
+
#as R. We can also access attributes of the R object
|
23
|
+
#
|
24
|
+
# puts e
|
25
|
+
# puts "t value: #{e.statistic['t']}"
|
26
|
+
#
|
3
27
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
e = r.t_test([1,2,3,4,5,6])
|
9
|
-
|
10
|
-
puts e
|
11
|
-
puts "t value: #{e.statistic['t']}"
|
12
|
-
|
13
|
-
f = r.t_test([1,2,3])
|
14
|
-
|
15
|
-
puts f
|
16
|
-
puts "t value: #{f.statistic['t']}"
|
28
|
+
if __FILE__ == $0
|
29
|
+
eval(IO.read($0).gsub(/^\#\s\s/,''))
|
30
|
+
end
|