-
Notifications
You must be signed in to change notification settings - Fork 1
/
rclg-demo.lisp
257 lines (180 loc) · 6.45 KB
/
rclg-demo.lisp
1
2
3
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
;; What is this talk of 'release'? Klingons do not make software
;; 'releases'. Our software 'escapes' leaving a bloody trail of
;; designers and quality assurance people in it's wake.
;;;#1 Load everything
;; if needed...? Shouldn't be, since rclg.asd ought to take care of
;; most of the issues that we have.
;; (asdf:operate 'asdf:compile-op 'cffi :force t)
;; (asdf:operate 'asdf:compile-op 'cffi)
;; (asdf:operate 'asdf:compile-op 'rclg :force t)
;; (asdf:operate 'asdf:compile-op 'rclg)
;;(asdf:operate 'asdf:load-op 'cffi)
(asdf:operate 'asdf:load-op 'rclg)
;;;#2 Go to where the functions are
(in-package :rclg-user)
;; Have we started yet?
rclg-init::*r-started*
rclg-init::*r-interactive*
;;;#3 Start R within Lisp
(start-rclg) ; => 0 ; if works, nil otherwise.
;; but if it fails, it could be related to...
;; and now we make sure it's working
;; rclg-init::*r-started*
(setf rclg-init::*r-interactive* 1) ; needed so that plot is interactive
(rclg-init::check-stack)
(r "Cstack_info")
;; library problems can cause things to fail here. libR.so needs to
;; be in the LD_LIBRARY_PATH prior to initialization of the common
;; lisp application.
;; For example, on Debian, you will need to add "/usr/lib/R/lib" to
;; the LD_LIBRARY_PATH environmental variable, i.e. for sh/bash/zsh:
;; export LD_LIBRARY_PATH=/usr/lib/R/lib:$LD_LIBRARY_PATH
;; or for csh/tcsh
;; setenv LD_LIBRARY_PATH "/usr/lib/R/lib:$LD_LIBRARY_PATH"
;; (not sure about the above, but it's something like that).
;
;;;#4 Demonstration of commands
;; Basically, you now have three choices:
;;
;; r --- calls R, and converts the result back to CL as best as it
;; can. If it can't convert, returns an unprotected sexp
;; (probably a bug, probably should be protected)
;;
;; rnb --- R no backconvert. Calls R, and returns a protected
;; unconverted R sexp. Useful when you want to manipulate
;; something on the R side and give it a CL name
;;
;; rnbi --- R no backconvert internal. Calls R, returns a protected
;; uncoverted R sexp. However, it's tagged differently, and
;; as soon as you use this as an argument to a function, it
;; unprotects the sexp. Useful for holding anonymous
;; intermediate R results you don't want to backconvert.
;;
;; Protection/unprotection controls whether R can GC the sexp.
;;
;; Example:
;;
;; CL-USER> (defparameter *x* (r seq 1 10))
;; *X*
;; CL-USER> (defparameter *y* (rnbi rnorm 10))
;; *Y*
;; CL-USER> *y*
;; #<sexp at 0x89A0238, PROTECT=R-PROTECT-UNTIL-USED>
;; CL-USER> (r plot *x* *y*)
;; NIL
;; NIL
;; CL-USER> *y*
;; #<sexp at 0x89A0238, PROTECT=NIL>
;; code used above
(defparameter *x* (r seq 1 10))
(defparameter *y* (rnbi rnorm 10))
(defparameter *y* (r rnorm 10))
*y*
(r plot *x* *y*)
*y*
;; This is for illustrative purposes only. It is not a "good" use of rnbi.
;; Really, you'll want rnbi to hold anonymous intermeditae results, like:
(r plot *x* (rnbi rnorm 10))
(r hist (r rnorm 10))
(r plot (list 1 2 3 2 3 4 5))
;; Notes:
;;
;; If the user protects the result of a call with rnb, it is the
;; user's responsibility to delete the sexp when it's no longer needed,
;; using rclg-control:unprotect-sexp. (It might be better to use a
;; modification of the old safe version that's lying around.)
;;
;; There is no way to ask R whether an sexp is protected or not.
;; Therefore, there is no real way to enforce the protection. If the user
;; goes around the API and calls %rf-unprotect-ptr or messes with the
;; description slot (slot-value sexp-holder 'protected), things can easily
;; get out of sync.
;; Examples of function use:
(r "Sys.getenv" "LD_LIBRARY_PATH")
(r "Sys.getenv" "LD_PRELOAD")
(r "ls")
(r "search")
(elt (r "search") 3)
(r "geterrmessage")
;; These don't work if we have library problems.
(r "library" "stats")
(r library "MASS")
;; (r "library" "Biobase") ;; Terminates if doesn't exists -- need to try/catch!
(setf my.lib "Biobase")
my.lib
(r library my.lib)
(r "ls")
(r "print.default" 3)
(r "rnorm" 10)
;; Working in the R space
(r assign "x" 5)
(r assign "x2" (list 1 2 3 5))
(r plot "x2" "x2") ; BOMBO.
(r assign "x2" #(1 2 3 5 3 4 5))
(r assign "z" "y") ;; unlike the above, this assigns character data
(r "ls")
;;(r "x2") ;halted "Error could not find function \"x2\""
(setf my.r.x2 (r get "x2")) ;; moving data from R to CL
my.r.x2
(r assign "x2" my.r.x2) ;; moving data from CL to R
(r "get" "x")
(r get "x2")
(r "get" "z")
(r get "z")
(r "ls")
(r assign "my.x" (r rnorm 10))
(r assign "my.x" (rnb rnorm 10))
(r get "my.x")
;; More sophisticated computation
(r "plot" #(2 3 3 2 1) #(3 5 7 3 2))
(r plot (list 1 2 3 4 5) (list 1 2 3 4 5) :main "My title")
(r plot :x (list 1 2 3 4 5) :y (list 5 4 3 4 5) :main "My title")
(r plot :y (list 5 4 3 4 5) :x (list 1 2 3 4 5) :main "My title")
(r plot (rnb rnorm 10) (rnb rnorm 10)
:main "silly" :xlab "xlabel" :ylab "ylabel")
(aref (r rnorm 10) 3) ;; pull out the 3rd value
;; create a CL function r-hist that calls the R function hist on a
;; sequence, returning no results. The keywords :main and :xlab are
;; passed with default values nil, and the other keywords are passed with
;; the chosen values.
(def-r-call (r-hist hist :no-result sequence) main
xlab (breaks 50) (probability t) (col "blue"))
;; then the function can be called:
(r-hist (rnbi rnorm 1000))
;; for instance.
;;;#5 Here is the TO MAKE WORK list (really, applications/tasks) that
;;; need to work (i.e. be do-able).
;;; a. Need to be able to read in datasets and summarize
(r assign "my.df" (r read.table "testdata.csv"))
(r get "my.df")
(r summary "my.df")
;; however the following will work...
(rnb data.frame
:x (r rnorm 10)
:y (r rnorm 10)) ; fine
(r data.frame
:x (r rnorm 10)
:y (r rnorm 10)) ; fine
(r summary (r t (r data.frame
:x (r rnorm 10)
:y (r rnorm 10)))) ; fine ; fine ; no.
;;; b. Need to be able to work with formulas as objects
(rnb as.formula "x ~ y") ; fine
(rnbi as.formula "x ~ y") ; fine
(r as.formula "x ~ y") ; barfs
;;; c. and the last is important so that we can easily fit models, so
;;; it needs to be fixed.
(r lm
:formula (rnb as.formula "x ~ y")
:data (rnb data.frame
:x (r rnorm 10)
:y (r rnorm 10)))
;;; d. How to handle connections?
;;; e. How to handle S4 objects?
;;; f. Hooks and finishing up conversion tools?
;;; how do we terminate the R session?
(r "q" "y") ;; fails.
;;; Local variables:
;;; mode: outline-minor
;;; outline-header-prefix: ";;;"
;;; End: