RSRuby 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +102 -0
- data/examples/bioc.rb +99 -0
- data/examples/dataframe.rb +15 -0
- data/examples/erobj.rb +16 -0
- data/ext/rsruby/Converters.c +657 -0
- data/ext/rsruby/Converters.h +74 -0
- data/ext/rsruby/R_eval.c +138 -0
- data/ext/rsruby/R_eval.h +40 -0
- data/ext/rsruby/extconf.rb +20 -0
- data/ext/rsruby/robj.c +169 -0
- data/ext/rsruby/rsruby.c +183 -0
- data/ext/rsruby/rsruby.h +80 -0
- data/lib/rsruby.rb +361 -0
- data/lib/rsruby/dataframe.rb +77 -0
- data/lib/rsruby/erobj.rb +97 -0
- data/test/tc_array.rb +58 -0
- data/test/tc_boolean.rb +27 -0
- data/test/tc_cleanup.rb +22 -0
- data/test/tc_eval.rb +15 -0
- data/test/tc_init.rb +0 -0
- data/test/tc_io.rb +60 -0
- data/test/tc_library.rb +20 -0
- data/test/tc_modes.rb +212 -0
- data/test/tc_robj.rb +87 -0
- data/test/tc_sigint.rb +10 -0
- data/test/tc_to_r.rb +146 -0
- data/test/tc_to_ruby.rb +155 -0
- data/test/tc_util.rb +19 -0
- data/test/tc_vars.rb +28 -0
- metadata +87 -0
data/ext/rsruby/rsruby.h
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
/*
|
2
|
+
* == Author
|
3
|
+
* Alex Gutteridge
|
4
|
+
*
|
5
|
+
* == Copyright
|
6
|
+
*Copyright (C) 2006 Alex Gutteridge
|
7
|
+
*
|
8
|
+
* The Original Code is the RPy python module.
|
9
|
+
*
|
10
|
+
* The Initial Developer of the Original Code is Walter Moreira.
|
11
|
+
* Portions created by the Initial Developer are Copyright (C) 2002
|
12
|
+
* the Initial Developer. All Rights Reserved.
|
13
|
+
*
|
14
|
+
* Contributor(s):
|
15
|
+
* Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
|
16
|
+
*
|
17
|
+
*This library is free software; you can redistribute it and/or
|
18
|
+
*modify it under the terms of the GNU Lesser General Public
|
19
|
+
*License as published by the Free Software Foundation; either
|
20
|
+
*version 2.1 of the License, or (at your option) any later version.
|
21
|
+
*
|
22
|
+
*This library is distributed in the hope that it will be useful,
|
23
|
+
*but WITHOUT ANY WARRANTY; without even the implied warranty of
|
24
|
+
*MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
25
|
+
*Lesser General Public License for more details.
|
26
|
+
*
|
27
|
+
*You should have received a copy of the GNU Lesser General Public
|
28
|
+
*License along with this library; if not, write to the Free Software
|
29
|
+
*Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
30
|
+
*/
|
31
|
+
|
32
|
+
#ifndef R_RUBY_MAIN
|
33
|
+
#define R_RUBY_MAIN
|
34
|
+
|
35
|
+
#include "ruby.h"
|
36
|
+
|
37
|
+
#include "R.h"
|
38
|
+
#include "Rdefines.h"
|
39
|
+
#include "Rinternals.h"
|
40
|
+
#include "Rdefines.h"
|
41
|
+
#include "Rdevices.h"
|
42
|
+
|
43
|
+
#include "signal.h"
|
44
|
+
|
45
|
+
#include "R_eval.h"
|
46
|
+
#include "Converters.h"
|
47
|
+
|
48
|
+
#define MAXIDSIZE 256
|
49
|
+
|
50
|
+
#define NO_CONVERSION 0
|
51
|
+
#define VECTOR_CONVERSION 1
|
52
|
+
#define BASIC_CONVERSION 2
|
53
|
+
#define CLASS_CONVERSION 3
|
54
|
+
#define PROC_CONVERSION 4
|
55
|
+
|
56
|
+
#define TOP_MODE 4
|
57
|
+
|
58
|
+
/* Missing definitions from Rinterface.h or RStartup.h */
|
59
|
+
# define CleanEd Rf_CleanEd
|
60
|
+
extern void CleanEd(void);
|
61
|
+
extern int R_CollectWarnings;
|
62
|
+
# define PrintWarnings Rf_PrintWarnings
|
63
|
+
extern void PrintWarnings(void);
|
64
|
+
|
65
|
+
void Init_rsruby();
|
66
|
+
|
67
|
+
void init_R(int argc, char *argv[0]);
|
68
|
+
void r_finalize(void);
|
69
|
+
|
70
|
+
static SEXP RecursiveRelease(SEXP obj, SEXP list);
|
71
|
+
static void Robj_dealloc(VALUE self);
|
72
|
+
|
73
|
+
VALUE shutdown(VALUE self);
|
74
|
+
VALUE get_fun(VALUE self, VALUE name);
|
75
|
+
VALUE rr_init(VALUE self);
|
76
|
+
|
77
|
+
VALUE RObj_lcall(VALUE self, VALUE args);
|
78
|
+
VALUE RObj_to_ruby(VALUE self, VALUE args);
|
79
|
+
|
80
|
+
#endif
|
data/lib/rsruby.rb
ADDED
@@ -0,0 +1,361 @@
|
|
1
|
+
#== Synopsis
|
2
|
+
#
|
3
|
+
#This class provides the ability to embed a full R
|
4
|
+
#interpreter inside a running Ruby script. R methods can
|
5
|
+
#then be called from the Ruby script and data passed between the
|
6
|
+
#R interpreter and the Ruby script. The code is based on a conversion
|
7
|
+
#of the RSPerl[http://www.omegahat.org/RSPerl/] and RPy[http://rpy.sourceforge.net/]
|
8
|
+
#modules which provide similar (and more) functionality for Perl and Python
|
9
|
+
#respectively.
|
10
|
+
#
|
11
|
+
#The main RSRuby class has Singleton module mixed in. This ensures that only
|
12
|
+
#one R interpreter is running in a script at any one time and that the
|
13
|
+
#interpreter can always be found. The embedded R interpreter is started by
|
14
|
+
#calling RSRuby.instance (See the RSRuby class for details). The returned
|
15
|
+
#RSRuby object represents the R interpreter and R functions are called by
|
16
|
+
#calling methods on this object.
|
17
|
+
#
|
18
|
+
#== Usage
|
19
|
+
#
|
20
|
+
# require 'rsruby'
|
21
|
+
#
|
22
|
+
# r = RSRuby.instance
|
23
|
+
# puts r.sum(1,2,3)
|
24
|
+
#
|
25
|
+
#Converting between R and Ruby data types is handled in a similar way to
|
26
|
+
#RPy and is explained in more detail in the manual (see Converters.c for the
|
27
|
+
#gory details).
|
28
|
+
#
|
29
|
+
#The default conversion system mapping between R types and Ruby classes is
|
30
|
+
#summarised here:
|
31
|
+
#
|
32
|
+
# - R Logicals (true/false) <=> Ruby true/false
|
33
|
+
# - R Integers <=> Ruby Fixnum/Bignum
|
34
|
+
# - R Real <=> Ruby Float
|
35
|
+
# - R Complex <=> Ruby Complex
|
36
|
+
# - R String <=> Ruby String
|
37
|
+
# - R Vector <=> Ruby Array or Hash
|
38
|
+
# - R List <=> Ruby Array or Hash
|
39
|
+
# - R Array <=> Ruby Array or Hash
|
40
|
+
# - R 'other' <=> Ruby RObj
|
41
|
+
#
|
42
|
+
#While this generally works fine for simple data structures, more complicated
|
43
|
+
#structures can loose information when converted to Ruby. Clever use of the
|
44
|
+
#more complicated custom conversion modes can usually avoid this.
|
45
|
+
#
|
46
|
+
#As shown above, calling R methods can be done by calling the same method
|
47
|
+
#on the RSRuby object. Some R methods contain '.' and other characters
|
48
|
+
#forbidden in Ruby method names. To call these methods substitute '_' for '.':
|
49
|
+
#
|
50
|
+
#Sample usage (to call R method 'as.list'):
|
51
|
+
#
|
52
|
+
# require 'rsruby'
|
53
|
+
#
|
54
|
+
# r = RSRuby.instance
|
55
|
+
# puts r.as_list([1,2,3])
|
56
|
+
#
|
57
|
+
#If a Hash is the last argument to an RSRuby method call then the hash is
|
58
|
+
#interpreted as a list of named arguments to the corresponding R function.
|
59
|
+
#Argument names can be given as Strings or Symbols. Argument order is not
|
60
|
+
#maintained in this case (because order is not maintained in Hashes). If
|
61
|
+
#named arguments and order are required then there is the lcall syntax where
|
62
|
+
#arguments are given as an array of two member arrays (where each two member
|
63
|
+
#array represents a name/argument pair). lcall is a method defined in the
|
64
|
+
#RObj class which represents functions and other non-convertible R objects.
|
65
|
+
#
|
66
|
+
#Calling an R method with no arguments returns the method object itself - it
|
67
|
+
#does not call the method. This may be changed in the future as it is somewhat
|
68
|
+
#confusing. However, the returned object can then be called or 'lcall'ed as
|
69
|
+
#required. It is also possible to return R variables in this way:
|
70
|
+
#
|
71
|
+
#E.g.
|
72
|
+
#
|
73
|
+
# require 'rsruby'
|
74
|
+
#
|
75
|
+
# r = RSRuby.instance
|
76
|
+
# norm = r.rnorm
|
77
|
+
# norm_dist = norm.call(100)
|
78
|
+
#
|
79
|
+
# r.plot(norm_dist,
|
80
|
+
# {:ylab => "TestY"})
|
81
|
+
# sleep(2)
|
82
|
+
#
|
83
|
+
#
|
84
|
+
#The final way to execute R code is to just evaluate a complete R expression
|
85
|
+
#The eval_R method provides this functionality. Pass a String to the method to
|
86
|
+
#see it evaluated by R:
|
87
|
+
#
|
88
|
+
# require 'rsruby'
|
89
|
+
#
|
90
|
+
# r = RSRuby.instance
|
91
|
+
# r.eval_R("a=43")
|
92
|
+
# puts r.a
|
93
|
+
#
|
94
|
+
#As an alternative to the method syntax, R objects and functions can be
|
95
|
+
#returned using []. This is required for weird R methods such as '$' or '[[':
|
96
|
+
#
|
97
|
+
# require 'rsruby'
|
98
|
+
#
|
99
|
+
# r = RSRuby.instance
|
100
|
+
# r.eval_R("a=43")
|
101
|
+
# puts r['a']
|
102
|
+
#
|
103
|
+
#R libraries can be loaded using the library method. Just provide the library
|
104
|
+
#name as a String:
|
105
|
+
#
|
106
|
+
# require 'rsruby'
|
107
|
+
#
|
108
|
+
# r = RSRuby.instance
|
109
|
+
# r.library("library_name")
|
110
|
+
#
|
111
|
+
#== Author
|
112
|
+
#Alex Gutteridge
|
113
|
+
#
|
114
|
+
#== Copyright
|
115
|
+
#Copyright (C) 2006 Alex Gutteridge
|
116
|
+
#
|
117
|
+
#The Original Code is the RPy python module.
|
118
|
+
#
|
119
|
+
#The Initial Developer of the Original Code is Walter Moreira.
|
120
|
+
#Portions created by the Initial Developer are Copyright (C) 2002
|
121
|
+
#the Initial Developer. All Rights Reserved.
|
122
|
+
#
|
123
|
+
#Contributor(s):
|
124
|
+
#Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
|
125
|
+
#
|
126
|
+
#This library is free software; you can redistribute it and/or
|
127
|
+
#modify it under the terms of the GNU Lesser General Public
|
128
|
+
#License as published by the Free Software Foundation; either
|
129
|
+
#version 2.1 of the License, or (at your option) any later version.
|
130
|
+
#
|
131
|
+
#This library is distributed in the hope that it will be useful,
|
132
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
133
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
134
|
+
#Lesser General Public License for more details.
|
135
|
+
#
|
136
|
+
#You should have received a copy of the GNU Lesser General Public
|
137
|
+
#License along with this library; if not, write to the Free Software
|
138
|
+
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
139
|
+
|
140
|
+
require 'rsruby/robj'
|
141
|
+
require 'rsruby.so'
|
142
|
+
require 'singleton'
|
143
|
+
|
144
|
+
require 'complex'
|
145
|
+
|
146
|
+
class RException < RuntimeError
|
147
|
+
end
|
148
|
+
|
149
|
+
class RSRuby
|
150
|
+
|
151
|
+
include Singleton
|
152
|
+
|
153
|
+
#Constants for conversion modes
|
154
|
+
TOP_CONVERSION = 4
|
155
|
+
PROC_CONVERSION = 4
|
156
|
+
CLASS_CONVERSION = 3
|
157
|
+
BASIC_CONVERSION = 2
|
158
|
+
VECTOR_CONVERSION = 1
|
159
|
+
NO_CONVERSION = 0
|
160
|
+
NO_DEFAULT = -1
|
161
|
+
|
162
|
+
alias c_initialize initialize
|
163
|
+
|
164
|
+
#Create a new RSRuby interpreter instance. The Singleton design pattern
|
165
|
+
#ensures that only one instance can be running in a script. Further
|
166
|
+
#calls to RSRuby.instance will return the original instance.
|
167
|
+
def initialize()
|
168
|
+
|
169
|
+
#Initialize in C
|
170
|
+
c_initialize
|
171
|
+
|
172
|
+
@@default_mode = NO_DEFAULT
|
173
|
+
|
174
|
+
@@class_table = {}
|
175
|
+
@@proc_table = {}
|
176
|
+
|
177
|
+
#Setup R object cache
|
178
|
+
@@cache = {}
|
179
|
+
@@cache['get'] = self.get_fun('get')
|
180
|
+
|
181
|
+
#Get constants
|
182
|
+
@@cache['TRUE'] = self.__getitem__('T')
|
183
|
+
@@cache['FALSE'] = self.__getitem__('F')
|
184
|
+
@@cache['NA'] = self.eval_R('NA')
|
185
|
+
# @@cache['NAN'] = self.eval_R('as.double(NA)')
|
186
|
+
@@cache['NaN'] = self.eval_R('NaN')
|
187
|
+
|
188
|
+
#help!
|
189
|
+
@@cache['helpfun'] = self.with_mode(NO_CONVERSION, self.__getitem__('help'))
|
190
|
+
|
191
|
+
#Catch errors
|
192
|
+
self.eval_R("options(error=expression(NULL))")
|
193
|
+
#disable errors
|
194
|
+
self.options('show.error.messages' => false)
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
#Handles method name conversion and calling of R functions
|
199
|
+
#If called without args the R function/varialbe is returned rather
|
200
|
+
#than called.
|
201
|
+
def method_missing(r_id,*args)
|
202
|
+
|
203
|
+
#Translate Ruby method call to R
|
204
|
+
robj_name = RSRuby.convert_method_name(r_id.to_s)
|
205
|
+
|
206
|
+
#Retrieve it
|
207
|
+
robj = self.__getitem__(robj_name)
|
208
|
+
|
209
|
+
#TODO perhaps this is not neccessary - always call these methods
|
210
|
+
#use the [] syntax for variables etc...
|
211
|
+
if args.length > 0
|
212
|
+
|
213
|
+
#convert arguments to lcall format
|
214
|
+
lcall_args = RSRuby.convert_args_to_lcall(args)
|
215
|
+
|
216
|
+
#Return result of calling object with lcall
|
217
|
+
#formatted args
|
218
|
+
return robj.lcall(lcall_args)
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
return robj
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
#As method_missing, but only returns the R function/object
|
227
|
+
#does not call it.
|
228
|
+
def [](r_id)
|
229
|
+
|
230
|
+
#Translate Ruby method call to R
|
231
|
+
robj_name = RSRuby.convert_method_name(r_id.to_s)
|
232
|
+
|
233
|
+
#Retrieve it
|
234
|
+
robj = self.__getitem__(robj_name)
|
235
|
+
|
236
|
+
#And return it
|
237
|
+
return robj
|
238
|
+
|
239
|
+
end
|
240
|
+
|
241
|
+
#Takes an #RObj representing an R function and sets the 'wrapping'
|
242
|
+
#mode for that function. Implemented for compatibility with RPy.
|
243
|
+
def with_mode(mode,func)
|
244
|
+
func.wrap = mode
|
245
|
+
return func
|
246
|
+
end
|
247
|
+
|
248
|
+
#Converts method names from Ruby compatible style into R style.
|
249
|
+
def RSRuby.convert_method_name(name)
|
250
|
+
if name.length > 1 and name[-1].chr == '_' and name[-2].chr != '_'
|
251
|
+
name = name[0..-2]
|
252
|
+
end
|
253
|
+
name.gsub!(/__/,'<-')
|
254
|
+
name.gsub!(/_/, '.')
|
255
|
+
return name
|
256
|
+
end
|
257
|
+
|
258
|
+
#Converts an array of arguments into lcall format. If the last element
|
259
|
+
#of the array is a Hash then the contents are interpreted as named
|
260
|
+
#arguments. lcall format is an Array of two member Arrays. Each two
|
261
|
+
#member array corresponds to a name/argument pair.
|
262
|
+
def RSRuby.convert_args_to_lcall(args)
|
263
|
+
|
264
|
+
lcall_args = []
|
265
|
+
|
266
|
+
args.each_with_index do |arg,i|
|
267
|
+
unless arg.kind_of?(Hash) and i == args.length-1
|
268
|
+
lcall_args.push(['',arg])
|
269
|
+
else
|
270
|
+
arg.each do |k,v|
|
271
|
+
lcall_args.push([k.to_s,v])
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
return lcall_args
|
277
|
+
|
278
|
+
end
|
279
|
+
|
280
|
+
#Sets the default conversion mode for RSRuby. The constants defined
|
281
|
+
#in #RSRuby should be used
|
282
|
+
def RSRuby.set_default_mode(m)
|
283
|
+
if m < -1 or m > TOP_CONVERSION
|
284
|
+
raise ArgumentError, "Invalid mode requested"
|
285
|
+
end
|
286
|
+
@@default_mode = m
|
287
|
+
end
|
288
|
+
#Returns the current default conversion mode as an Integer.
|
289
|
+
def RSRuby.get_default_mode
|
290
|
+
@@default_mode
|
291
|
+
end
|
292
|
+
|
293
|
+
#TODO - input/output setting methods don't work atm
|
294
|
+
def RSRuby.set_rsruby_input(m)
|
295
|
+
@@rsruby_input = m
|
296
|
+
end
|
297
|
+
def RSRuby.get_rsruby_input
|
298
|
+
@@rsruby_input
|
299
|
+
end
|
300
|
+
|
301
|
+
def RSRuby.set_rsruby_output(m)
|
302
|
+
@@rsruby_output = m
|
303
|
+
end
|
304
|
+
def RSRuby.get_rsruby_output
|
305
|
+
@@rsruby_output
|
306
|
+
end
|
307
|
+
|
308
|
+
def RSRuby.set_rsruby_showfiles(m)
|
309
|
+
@@rsruby_showfiles = m
|
310
|
+
end
|
311
|
+
def RSRuby.get_rsruby_showfiles
|
312
|
+
@@rsruby_showfiles
|
313
|
+
end
|
314
|
+
|
315
|
+
#Returns the current class table Hash for RSRuby.
|
316
|
+
def class_table
|
317
|
+
@@class_table
|
318
|
+
end
|
319
|
+
|
320
|
+
#Sets the RSRuby class table Hash.
|
321
|
+
def class_table=(h)
|
322
|
+
@@class_table = h
|
323
|
+
end
|
324
|
+
|
325
|
+
#Returns the current proc table Hash for RSRuby.
|
326
|
+
def proc_table
|
327
|
+
@@proc_table
|
328
|
+
end
|
329
|
+
|
330
|
+
#Sets the RSRuby proc table Hash.
|
331
|
+
def proc_table=(h)
|
332
|
+
@@proc_table = h
|
333
|
+
end
|
334
|
+
|
335
|
+
#Evaluates the given string in R. Returns the result of the evaluation.
|
336
|
+
def eval_R(s)
|
337
|
+
self.eval(self.parse(:text => s))
|
338
|
+
end
|
339
|
+
|
340
|
+
#Wraps the R help function.
|
341
|
+
def help(*args)
|
342
|
+
helpobj = @@cache['helpfun'].call(args)
|
343
|
+
self.print(helpobj)
|
344
|
+
end
|
345
|
+
|
346
|
+
:private
|
347
|
+
def __getitem__(name)
|
348
|
+
|
349
|
+
#Find the identifier and cache (unless already cached)
|
350
|
+
unless @@cache.has_key?(name)
|
351
|
+
@@cache[name] = @@cache['get'].lcall([['',name]])
|
352
|
+
end
|
353
|
+
|
354
|
+
#Retrieve object from cache
|
355
|
+
robj = @@cache[name]
|
356
|
+
|
357
|
+
return robj
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#== Synopsis
|
2
|
+
#
|
3
|
+
#This is an extended #ERObj class inspired by the example given in the RPy
|
4
|
+
#manual used for R data frames.
|
5
|
+
#As with ERobj, methods caught by method_missing are converted into attribute
|
6
|
+
#calls on the R dataframe it represents. The rows and columns methods give
|
7
|
+
#access to the column and row names.
|
8
|
+
#
|
9
|
+
#== Usage
|
10
|
+
#
|
11
|
+
#See examples/dataframe.rb for examples of usage.
|
12
|
+
#
|
13
|
+
#--
|
14
|
+
#== Author
|
15
|
+
#Alex Gutteridge
|
16
|
+
#
|
17
|
+
#== Copyright
|
18
|
+
#Copyright (C) 2006 Alex Gutteridge
|
19
|
+
#
|
20
|
+
# The Original Code is the RPy python module.
|
21
|
+
#
|
22
|
+
# The Initial Developer of the Original Code is Walter Moreira.
|
23
|
+
# Portions created by the Initial Developer are Copyright (C) 2002
|
24
|
+
# the Initial Developer. All Rights Reserved.
|
25
|
+
#
|
26
|
+
# Contributor(s):
|
27
|
+
# Gregory R. Warnes <greg@warnes.net> (RPy Maintainer)
|
28
|
+
#
|
29
|
+
#This library is free software; you can redistribute it and/or
|
30
|
+
#modify it under the terms of the GNU Lesser General Public
|
31
|
+
#License as published by the Free Software Foundation; either
|
32
|
+
#version 2.1 of the License, or (at your option) any later version.
|
33
|
+
#
|
34
|
+
#This library is distributed in the hope that it will be useful,
|
35
|
+
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
36
|
+
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
37
|
+
#Lesser General Public License for more details.
|
38
|
+
#
|
39
|
+
#You should have received a copy of the GNU Lesser General Public
|
40
|
+
#License along with this library; if not, write to the Free Software
|
41
|
+
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
42
|
+
#++
|
43
|
+
|
44
|
+
require 'rsruby'
|
45
|
+
require 'rsruby/erobj'
|
46
|
+
|
47
|
+
class DataFrame < ERObj
|
48
|
+
|
49
|
+
#Returns an array of the row names used in the R data frame.
|
50
|
+
def rows
|
51
|
+
return @r.attr(@robj, 'row.names')
|
52
|
+
end
|
53
|
+
|
54
|
+
#Returns an array of the column names used in the R data frame.
|
55
|
+
def columns
|
56
|
+
cols = @r.colnames(@robj)
|
57
|
+
cols = [cols] unless cols.class == 'Array'
|
58
|
+
return cols
|
59
|
+
end
|
60
|
+
|
61
|
+
def method_missing(attr)
|
62
|
+
attr = attr.to_s
|
63
|
+
mode = RSRuby.get_default_mode
|
64
|
+
RSRuby.set_default_mode(RSRuby::BASIC_CONVERSION)
|
65
|
+
column_names = @r.colnames(@robj)
|
66
|
+
if attr == column_names or column_names.include?(attr)
|
67
|
+
RSRuby.set_default_mode(mode)
|
68
|
+
return @r['$'].call(@robj,attr.to_s)
|
69
|
+
end
|
70
|
+
|
71
|
+
#? Not sure what here...
|
72
|
+
RSRuby.set_default_mode(mode)
|
73
|
+
return super(attr)
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|