Class: Renjin

Inherits:
Object
  • Object
show all
Defined in:
lib/JRubyR/list.rb,
lib/JRubyR/rbsexp.rb,
lib/JRubyR/rbsexp.rb,
lib/JRubyR/renjin.rb,
lib/JRubyR/function.rb,
lib/JRubyR/sequence.rb,
lib/JRubyR/dataframe.rb,
lib/JRubyR/as_mdarray.rb,
lib/JRubyR/attributes.rb,
lib/JRubyR/environment.rb,
lib/JRubyR/logical_value.rb,
lib/JRubyR/vector.rb,
lib/JRubyR/vector.rb

Overview

Defined Under Namespace

Modules: Index, RBSexp Classes: Attributes, Closure, ComplexVector, DataFrame, Environment, Function, List, Logical, Primitive, RubySexp, Sequence, Vector

Constant Summary collapse

ParseError =

Parse error

Class.new(Exception)

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeRenjin


R is invoked within a Ruby script (or the interactive “irb” prompt denoted >>) using:

>> require "scicom"

The previous statement reads the definition of the RinRuby class into the current Ruby interpreter and creates an instance of the RinRuby class named R. There is a second method for starting an instance of R which allows the user to use any name for the instance, in this case myr:

>> require "scicom"
>> myr = RinRuby.new
>> myr.eval "rnorm(1)"

Any number of independent instances of R can be created in this way.




71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/JRubyR/renjin.rb', line 71

def initialize

  @platform = 
    case RUBY_PLATFORM
    when /mswin/ then 'windows'
    when /mingw/ then 'windows'
    when /bccwin/ then 'windows'
    when /cygwin/ then 'windows-cygwin'
    when /java/
      require 'java' #:nodoc:
      if java.lang.System.getProperty("os.name") =~ /[Ww]indows/
        'windows-java'
      else
        'default-java'
      end
    else 'default'
    end

  factory = Java::JavaxScript.ScriptEngineManager.new()
  @engine = factory.getEngineByName("Renjin")
  
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args) ⇒ Object





141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/JRubyR/renjin.rb', line 141

def method_missing(symbol, *args)

  name = symbol.id2name
  name.gsub!(/__/,".")
  # Method 'rclass' is a substitute for R method 'class'.  Needed, as 'class' is also
  # a Ruby method on an object
  name.gsub!("rclass", "class")

  if name =~ /(.*)=$/
    super if args.length != 1
    ret = assign($1,args[0])
  else
    # super if args.length != 0
    if (args.length == 0)
      # is_var = false
      # Try to see if name is a variable or a method.
      ret = (eval("\"#{name}\" %in% ls()").gt)? eval("#{name}") : eval("#{name}()")
    else
      params = parse(*args)
      # p "#{name}(#{params})"
      ret = eval("#{name}(#{params})")
    end
  end

  ret

end

Class Attribute Details

.stackObject

Returns the value of attribute stack.



42
43
44
# File 'lib/JRubyR/renjin.rb', line 42

def stack
  @stack
end

Instance Attribute Details

#engineObject (readonly)





49
50
51
# File 'lib/JRubyR/renjin.rb', line 49

def engine
  @engine
end

Instance Method Details

#assign(name, value) ⇒ Object


Data is copied from Ruby to R using the assign method or a short-hand equivalent. For example:

>> names = ["Lisa","Teasha","Aaron","Thomas"]
>> R.assign "people", names
>> R.eval "sort(people)"

produces the following :

[1] "Aaron"     "Lisa"     "Teasha" "Thomas"

The short-hand equivalent to the assign method is simply:

>> R.people = names

Some care is needed when using the short-hand of the assign method since the label (i.e., people in this case) must be a valid method name in Ruby. For example, R.copy.of.names = names will not work, but R.copy_of_names = names is permissible.

The assign method supports Ruby variables of type Fixnum (i.e., integer), Bignum (i.e., integer), Float (i.e., double), String, and arrays of one of those three fundamental types. Note that Fixnum or Bignum values that exceed the capacity of R’s integers are silently converted to doubles. Data in other formats must be coerced when copying to R.

Parameters that can be passed to the assign method:

  • name: The name of the variable desired in R.

  • value: The value the R variable should have.

The assign method is an alternative to the simplified method, with some additional flexibility. When using the simplified method, the parameters of name and value are automatically used, in other words:

>> R.test = 144

is the same as:

>> R.assign("test",144)

Of course it would be confusing to use the shorthand notation to assign a variable named eval, echo, or any other already defined function. RinRuby would assume you were calling the function, rather than trying to assign a variable.

When assigning an array containing differing types of variables, RinRuby will follow R’s conversion conventions. An array that contains any Strings will result in a character vector in R. If the array does not contain any Strings, but it does contain a Float or a large integer (in absolute value), then the result will be a numeric vector of Doubles in R. If there are only integers that are suffciently small (in absolute value), then the result will be a numeric vector of integers in R.




344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/JRubyR/renjin.rb', line 344

def assign(name, value)

  original_value = value

  if ((value.is_a? MDArray) || (value.is_a? RubySexp))
    if (value.sexp != nil)
      # MDArray already represented in R
      value = value.sexp
    else
      value = build_vector(value)
    end
  elsif (value == nil)
    value = NULL
  end

  @engine.put(name, value)
  original_value
  
end

#build_vector(array) ⇒ Object


Builds a Renjin vector from an MDArray. Should be private, but public for testing.




401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
# File 'lib/JRubyR/renjin.rb', line 401

def build_vector(array)
  
  shape = array.shape
  index = array.nc_array.getIndex()
  # index = MDArray.index_factory(shape)
  # representation of shape in R is different from shape in MDArray.  Convert MDArray
  # shape to R shape.
  if (shape.size > 2)
    shape.reverse!
    shape[0], shape[1] = shape[1], shape[0]
  end
  # AttributeMap attributes = AttributeMap.builder().setDim(new IntVector(dim)).build();
  attributes = Java::OrgRenjinSexp::AttributeMap.builder()
    .setDim(Java::OrgRenjinSexp::IntArrayVector.new(*(shape))).build()
  vector = Java::RbScicom::MDDoubleVector.new(array.nc_array, attributes, index,
                                              index.stride)
  
end

#d(value) ⇒ Object



197
198
199
# File 'lib/JRubyR/renjin.rb', line 197

def d(value)
  R.eval("#{value}")
end

#direct_eval(expression) ⇒ Object


Evaluates an expression but does not wrap the return in a RubySexp. Needed for intermediate evaluation done by internal methods. In principle, should not be called by users.




228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/JRubyR/renjin.rb', line 228

def direct_eval(expression)
  begin
    ret = @engine.eval(expression)
  rescue Java::OrgRenjinEval::EvalException => e 
    p e.message
  ensure
=begin
    Renjin.stack.each do |sexp|
      sexp.destroy
    end
=end
  end

  ret

end

#eval(expression) ⇒ Object





205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/JRubyR/renjin.rb', line 205

def eval(expression)
  begin
    ret = Renjin::RubySexp.build(@engine.eval(expression))
  rescue Java::OrgRenjinEval::EvalException => e 
    p e.message
  rescue Java::OrgRenjinParser::ParseException => e
    p e.message
  ensure
    Renjin.stack.each do |sexp|
      sexp.destroy
    end
  end

  ret

end

#fassign(sexp, function, value) ⇒ Object


function is either a function name alone represented by a ruby symbol or a hash with the function name and its arguments or indexes Ex:

fassign(sexp, :rowname, "x1")
fassign(sexp, {f: :rowname, index: [[1]]}, "x1")
fassign(sexp, {f: :somefunc, params: "(2, 3, 4)"}, "x1")



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/JRubyR/renjin.rb', line 381

def fassign(sexp, function, value)

  if (function.is_a? Hash)
    index = function[:index]
    params = function[:params]
    function = function[:f]
    if (index)
      R.eval("#{function.to_s}(#{sexp.r})#{index} = #{value.r}")
    else
    end
  else
    R.eval("#{function.to_s}(#{sexp.r}) = #{value.r}")
  end

end

#finite?(x) ⇒ Boolean



Returns:

  • (Boolean)


133
134
135
# File 'lib/JRubyR/renjin.rb', line 133

def finite?(x)
  R.is__finite(x)
end

#i(value) ⇒ Object



193
194
195
# File 'lib/JRubyR/renjin.rb', line 193

def i(value)
  R.eval("#{value}L")
end

#LETTERSObject



177
178
179
# File 'lib/JRubyR/renjin.rb', line 177

def LETTERS
  R.eval("LETTERS")
end

#lettersObject



181
182
183
# File 'lib/JRubyR/renjin.rb', line 181

def letters
  R.eval("letters")
end

#month__abbObject



185
186
187
# File 'lib/JRubyR/renjin.rb', line 185

def month__abb
  R.eval("month.abb")
end

#month__nameObject



189
190
191
# File 'lib/JRubyR/renjin.rb', line 189

def month__name
  R.eval("month.name")
end

#na?(x) ⇒ Boolean


The integer constant used to designate elements or values that are missing in the statistical sense, or literally “Not Available”. For integers (Fixnum) this is represented as the minimum integer from Java Integer.MIN_VALUE


Returns:

  • (Boolean)


125
126
127
# File 'lib/JRubyR/renjin.rb', line 125

def na?(x)
  R.is__na(x)
end

#nan?(x) ⇒ Boolean



Returns:

  • (Boolean)


114
115
116
# File 'lib/JRubyR/renjin.rb', line 114

def nan?(x)
  is__nan(x)
end

#parse(*args) ⇒ Object





249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
# File 'lib/JRubyR/renjin.rb', line 249

def parse(*args)

  params = Array.new
  
  args.each do |arg|
    if (arg.is_a? Numeric)
      params << arg
    elsif(arg.is_a? String)
      params << "\"#{arg}\""
    elsif (arg.is_a? Symbol)
      var = eval("#{arg.to_s}")
      params << var.r
    elsif (arg.is_a? TrueClass)
      params << "TRUE"
    elsif (arg.is_a? FalseClass)
      params << "FALSE"
    elsif (arg == nil)
      params << "NULL"
    elsif (arg.is_a? NegRange)
      final_value = (arg.exclude_end?)? (arg.end - 1) : arg.end
      params << "-(#{arg.begin}:#{final_value})"
    elsif (arg.is_a? Range)
      final_value = (arg.exclude_end?)? (arg.end - 1) : arg.end
      params << "(#{arg.begin}:#{final_value})"
    elsif (arg.is_a? Hash)
      arg.each_pair do |key, value|
        params << "#{key.to_s} = #{parse(value)}"
      end
    elsif ((arg.is_a? Renjin::RubySexp) || (arg.is_a? Array) || (arg.is_a? MDArray))
      params << arg.r
    # elsif 
    #  params << arg.inspect
    else
      raise "Unknown parameter type for R: #{arg}"
    end
    
  end

  params.join(",")
    
end

#piObject


R built-in constants




173
174
175
# File 'lib/JRubyR/renjin.rb', line 173

def pi
  R.eval("pi")
end

#pull(name) ⇒ Object





368
369
370
# File 'lib/JRubyR/renjin.rb', line 368

def pull(name)
  eval(name)
end

#ri(shape) ⇒ Object


Converts an MDArray shape or index onto an equivalent R shape or index




98
99
100
101
102
103
104
105
106
107
108
# File 'lib/JRubyR/renjin.rb', line 98

def ri(shape)

  rshape = shape.clone

  if (rshape.size > 2)
    rshape.reverse!
    rshape[0], rshape[1] = rshape[1], rshape[0]
  end
  rshape.map{ |val| (val + 1) }

end