jasagiri @ ウィキ
RSRubyReferenceManualChapter5
最終更新:
jasagiri
第5章 RSRuby の拡張
例
ほとんどの簡単なアプリケーションでは基本の変換モードで十分ですが、 R オブジェクトを使うなら基本タイプを超えていけます。 PROC_CONVERSION and CLASS_CONVERSION モードではじめるのに必要でしょう。カスタム Ruby クラスと連携してほんとに強力なシステムを作ることが出来ます。
5.0.1 Enhanced RObj
RPy マニュアルのデモと同様な RObj クラスの拡張例を示します。 R オブジェクトを探す属性は method_missing を使うよう置き換えています。また、R によって出力された文字列を置換するメソッドのデモも示します。 This code is included in the RSRuby distribution and can be activated by require-ing rsruby/erobj and setting the proc table appropriately as shown:
class ERObj @@x = 1 def initialize(robj) @robj = robj @r = RSRuby.instance end
The ERObj initialization method simply stores the wrapped RObj and the RSRuby interpreter.
def as_r @robj.as_r end def lcall(args) @robj.lcall(args) end
The as_r and lcall methods simply delegate to the same methods in the wrapped underlying RObj.
def to_s @@x += 1 mode = RSRuby.get_default_mode RSRuby.set_default_mode(RSRuby::NO_CONVERSION) a = @r.textConnection("tmpobj#{@@x}",’w’) RSRuby.set_default_mode(RSRuby::BASIC_CONVERSION) @r.sink(:file => a, :type => ’output’) @r.print_(@robj) @r.sink.call() @r.close_connection(a) str = @r["tmpobj#{@@x}"].join("\n") RSRuby.set_default_mode(mode) return str end
The to_s method makes the R interpreter print to the tmpobj variable using the textConnection and sink functions. This is then retrieved and returned as the string representation of the object for Ruby.
def method_missing(attr) mode = RSRuby.get_default_mode RSRuby.set_default_mode(RSRuby::BASIC_CONVERSION) e = @r[’\$’].call(@robj,attr.to_s) RSRuby.set_default_mode(mode) return e end end
The method missing function returns the attribute with the same name as the missing method from the wrapped RObj. To use the ERObj class we can set the proc table to return a new ERObj with every conversion.
irb> r = RSRuby.instance => #<RSRuby:0xb7baf320> irb> r.proc_table[lambda{|x| true}] = lambda{|x| ERObj.new(x)} => #<Proc:0xb7ba68ec@(irb):2> irb> RSRuby.set_default_mode(RSRuby::PROC_CONVERSION) => 4
To test the returned class we use the R t.test function, which returns an R list. Note the string representation of the returned object which matches the string form given by R.
irb> e = r.t_test([1,2,3,4,5,6]) => #<ERObj:0xb7b9d918> irb> puts e One Sample t-test data: c(1, 2, 3, 4, 5, 6) t = 4.5826, df = 5, p-value = 0.005934
alternative hypothesis: true mean is not equal to 0 95 percent confidence interval: 1.536686 5.463314 sample estimates:
mean of x 3.5 => nil irb> e.statistic[’t’] => 4.58257569495584
5.0.2 ArrayFields
The default conversion mode converts R lists into Ruby Hashes. This changes the seman- tics of the returned object because R lists retain order information while Ruby Hashes are unordered. To fix this we can plug a new method in to return Arrays extended by the ArrayFields gem:
require ’rubygems’ require_gem ’arrayfields’ require ’rsruby’ test_proc = lambda{|x| !(RSRuby.instance.attr(x,’names’).nil?)}
This Proc tests the given object to see if the names attribute is set. If so, the following Proc is used to convert the object.
conv_proc = lambda{|x| hash = x.to_ruby array = [] array.fields = RSRuby.instance.attr(x,’names’) RSRuby.instance.attr(x,’names’).each{|f| array[f] = hash[f]} return array }
We then setup the proc table with these procs and test using the R t.test function.
r = RSRuby.instance r.t_test.autoconvert(RSRuby::PROC_CONVERSION) r.proc_table[test_proc] = conv_proc r.t_test([1,2,3]).each_pair{|f,v| puts "#{f} - #{v}"}
Note that the point here is that the list returned by t.test is converted to an Array (with the Arrayfields extensions), which retains order information unlike the Hash it would be converted to otherwise.
5.0.3 DataFrames
DataFrames は R プログラミングでは有用なオブジェクトです。