require 'rbbt/util/R' module R class << self attr_accessor :model_dir def self.model_dir=(model_dir) @model_dir = Path === model_dir ? model_dir : Path.setup(model_dir) end def self.model_dir @model_dir ||= Rbbt.var.R.models end end self.model_dir = Rbbt.var.R.models class Model R_METHOD = :eval attr_accessor :name, :formula def initialize(name, formula, options = {}) @name = name @formula = formula @options = options || {} end def colClasses(tsv) "c('character', " << (tsv.fields.collect{|f| R.ruby2R(@options[f] ? @options[f].to_s : ":NA") } * ", ") << ")" end def r_options(tsv) {:R_open => "colClasses=#{colClasses(tsv)}", :R_method => (@options[:R_method] || R_METHOD), :source => @options[:source]} end def model_file @model_file ||= R.model_dir[Misc.name2basename([name, Misc.name2basename(formula)] * ": ")].find end def update(tsv, field = "Prediction") tsv.R <<-EOF, r_options(tsv) model = rbbt.model.load('#{model_file}'); model = update(model, data); save(model, file='#{model_file}'); data = NULL EOF end def self.groom(tsv, formula) tsv = tsv.to_list if tsv.type == :single if formula.include? tsv.key_field and not tsv.fields.include? tsv.key_field tsv = tsv.add_field tsv.key_field do |k,v| k end end tsv end def predict(tsv, field = "Prediction") tsv = Model.groom tsv, formula tsv.R <<-EOF, r_options(tsv) model = rbbt.model.load('#{model_file}'); data.groomed = rbbt.model.groom(data,formula=#{formula}) data$#{field} = predict(model, data.groomed); EOF end def exists? File.exists? model_file end def fit(tsv, method='lm', args = {}) args_str = "" args_str = args.collect{|name,value| [name,R.ruby2R(value)] * "=" } * ", " args_str = ", " << args_str unless args_str.empty? tsv = Model.groom(tsv, formula) FileUtils.mkdir_p File.dirname(model_file) unless File.exists?(File.dirname(model_file)) tsv.R <<-EOF, r_options(tsv) model = rbbt.model.fit(data, #{formula}, method=#{method}#{args_str}) save(model, file='#{model_file}') data = NULL EOF end end end