passagemath-standard-no-symbolics 10.6.45__cp313-cp313-macosx_13_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_standard_no_symbolics/__init__.py +1 -0
- passagemath_standard_no_symbolics-10.6.45.data/scripts/sage-grep +5 -0
- passagemath_standard_no_symbolics-10.6.45.data/scripts/sage-grepdoc +5 -0
- passagemath_standard_no_symbolics-10.6.45.data/scripts/sage-list-packages +103 -0
- passagemath_standard_no_symbolics-10.6.45.dist-info/METADATA +150 -0
- passagemath_standard_no_symbolics-10.6.45.dist-info/RECORD +83 -0
- passagemath_standard_no_symbolics-10.6.45.dist-info/WHEEL +6 -0
- passagemath_standard_no_symbolics-10.6.45.dist-info/top_level.txt +2 -0
- sage/all.py +207 -0
- sage/all_cmdline.py +36 -0
- sage/cli/__init__.py +61 -0
- sage/cli/__main__.py +5 -0
- sage/cli/eval_cmd.py +45 -0
- sage/cli/eval_cmd_test.py +25 -0
- sage/cli/interactive_shell_cmd.py +28 -0
- sage/cli/notebook_cmd.py +51 -0
- sage/cli/notebook_cmd_test.py +39 -0
- sage/cli/options.py +26 -0
- sage/cli/run_file_cmd.py +50 -0
- sage/cli/version_cmd.py +26 -0
- sage/databases/all.py +83 -0
- sage/databases/cubic_hecke_db.py +1527 -0
- sage/dynamics/all.py +31 -0
- sage/dynamics/surface_dynamics_deprecation.py +32 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/mwrank/PRIMES +1 -0
- sage/ext_data/nbconvert/postprocess.py +48 -0
- sage/ext_data/nbconvert/rst_sage.tpl +99 -0
- sage/ext_data/nodoctest +0 -0
- sage/ext_data/notebook-ipython/kernel.json.in +11 -0
- sage/ext_data/notebook-ipython/logo-64x64.png +0 -0
- sage/ext_data/notebook-ipython/logo.svg +352 -0
- sage/ext_data/valgrind/pyalloc.supp +58 -0
- sage/ext_data/valgrind/sage-additional.supp +417 -0
- sage/ext_data/valgrind/sage.supp +43 -0
- sage/ext_data/valgrind/valgrind-python.supp +480 -0
- sage/geometry/all.py +12 -0
- sage/groups/matrix_gps/pickling_overrides.py +110 -0
- sage/homology/tests.py +66 -0
- sage/interacts/algebra.py +20 -0
- sage/interacts/all.py +25 -0
- sage/interacts/calculus.py +24 -0
- sage/interacts/fractals.py +18 -0
- sage/interacts/geometry.py +19 -0
- sage/interacts/library.py +1950 -0
- sage/interacts/library_cython.cpython-313-darwin.so +0 -0
- sage/interacts/statistics.py +19 -0
- sage/interfaces/axiom.py +1002 -0
- sage/interfaces/kash.py +834 -0
- sage/interfaces/lie.py +950 -0
- sage/interfaces/matlab.py +413 -0
- sage/interfaces/mupad.py +686 -0
- sage/interfaces/octave.py +858 -0
- sage/interfaces/phc.py +943 -0
- sage/interfaces/psage.py +189 -0
- sage/interfaces/qsieve.py +4 -0
- sage/interfaces/r.py +2096 -0
- sage/interfaces/read_data.py +46 -0
- sage/interfaces/scilab.py +576 -0
- sage/interfaces/tests.py +81 -0
- sage/libs/all.py +11 -0
- sage/libs/cremona/__init__.py +0 -0
- sage/libs/mwrank/__init__.py +0 -0
- sage/logic/all.py +3 -0
- sage/logic/booleval.py +160 -0
- sage/logic/boolformula.py +1490 -0
- sage/logic/logic.py +856 -0
- sage/logic/logicparser.py +696 -0
- sage/logic/logictable.py +272 -0
- sage/logic/propcalc.py +311 -0
- sage/misc/all.py +28 -0
- sage/misc/lazy_attribute.pyi +11 -0
- sage/rings/all.py +48 -0
- sage/rings/commutative_algebra.py +38 -0
- sage/rings/finite_rings/all.py +21 -0
- sage/rings/numbers_abc.py +58 -0
- sage/rings/polynomial/all.py +22 -0
- sage/rings/polynomial/convolution.py +421 -0
- sage/symbolic/all__sagemath_standard_no_symbolics.py +0 -0
sage/interfaces/r.py
ADDED
|
@@ -0,0 +1,2096 @@
|
|
|
1
|
+
# sage.doctest: needs rpy2
|
|
2
|
+
r"""
|
|
3
|
+
Interfaces to R
|
|
4
|
+
|
|
5
|
+
This is the reference to the Sagemath R interface, usable from any
|
|
6
|
+
Sage program.
|
|
7
|
+
|
|
8
|
+
The %r interface creating an R cell in the sage
|
|
9
|
+
notebook is described in the Notebook manual.
|
|
10
|
+
|
|
11
|
+
The %R and %%R interface creating an R line or an R cell in the
|
|
12
|
+
Jupyter notebook are briefly described at the end of this page. This
|
|
13
|
+
documentation will be expanded and placed in the Jupyter notebook
|
|
14
|
+
manual when this manual exists.
|
|
15
|
+
|
|
16
|
+
The following examples try to follow "An Introduction to R" which can
|
|
17
|
+
be found at http://cran.r-project.org/doc/manuals/R-intro.html .
|
|
18
|
+
|
|
19
|
+
EXAMPLES:
|
|
20
|
+
|
|
21
|
+
Simple manipulations; numbers and vectors
|
|
22
|
+
|
|
23
|
+
The simplest data structure in R is the numeric vector which
|
|
24
|
+
consists of an ordered collection of numbers. To create a
|
|
25
|
+
vector named `x` using the R interface in Sage, you pass the
|
|
26
|
+
R interpreter object a list or tuple of numbers::
|
|
27
|
+
|
|
28
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7]); x
|
|
29
|
+
[1] 10.4 5.6 3.1 6.4 21.7
|
|
30
|
+
|
|
31
|
+
You can invert elements of a vector x in R by using the
|
|
32
|
+
invert operator or by doing 1/x::
|
|
33
|
+
|
|
34
|
+
sage: ~x
|
|
35
|
+
[1] 0.09615385 0.17857143 0.32258065 0.15625000 0.04608295
|
|
36
|
+
sage: 1/x
|
|
37
|
+
[1] 0.09615385 0.17857143 0.32258065 0.15625000 0.04608295
|
|
38
|
+
|
|
39
|
+
The following assignment creates a vector `y` with 11 entries which
|
|
40
|
+
consists of two copies of `x` with a 0 in between::
|
|
41
|
+
|
|
42
|
+
sage: y = r([x,0,x]); y
|
|
43
|
+
[1] 10.4 5.6 3.1 6.4 21.7 0.0 10.4 5.6 3.1 6.4 21.7
|
|
44
|
+
|
|
45
|
+
Vector Arithmetic
|
|
46
|
+
|
|
47
|
+
The following command generates a new vector `v` of length 11 constructed
|
|
48
|
+
by adding together (element by element) `2x` repeated 2.2 times, `y`
|
|
49
|
+
repeated just once, and 1 repeated 11 times::
|
|
50
|
+
|
|
51
|
+
sage: v = 2*x+y+1; v
|
|
52
|
+
[1] 32.2 17.8 10.3 20.2 66.1 21.8 22.6 12.8 16.9 50.8 43.5
|
|
53
|
+
|
|
54
|
+
One can compute the sum of the elements of an R vector in the following
|
|
55
|
+
two ways::
|
|
56
|
+
|
|
57
|
+
sage: sum(x)
|
|
58
|
+
[1] 47.2
|
|
59
|
+
sage: x.sum()
|
|
60
|
+
[1] 47.2
|
|
61
|
+
|
|
62
|
+
One can calculate the sample variance of a list of numbers::
|
|
63
|
+
|
|
64
|
+
sage: ((x-x.mean())^2/(x.length()-1)).sum()
|
|
65
|
+
[1] 53.853
|
|
66
|
+
sage: x.var()
|
|
67
|
+
[1] 53.853
|
|
68
|
+
|
|
69
|
+
sage: x.sort()
|
|
70
|
+
[1] 3.1 5.6 6.4 10.4 21.7
|
|
71
|
+
sage: x.min()
|
|
72
|
+
[1] 3.1
|
|
73
|
+
sage: x.max()
|
|
74
|
+
[1] 21.7
|
|
75
|
+
sage: x
|
|
76
|
+
[1] 10.4 5.6 3.1 6.4 21.7
|
|
77
|
+
|
|
78
|
+
sage: r(-17).sqrt()
|
|
79
|
+
[1] NaN
|
|
80
|
+
sage: r('-17+0i').sqrt()
|
|
81
|
+
[1] 0+4.123106i
|
|
82
|
+
|
|
83
|
+
Generating an arithmetic sequence::
|
|
84
|
+
|
|
85
|
+
sage: r('1:10')
|
|
86
|
+
[1] 1 2 3 4 5 6 7 8 9 10
|
|
87
|
+
|
|
88
|
+
Because ``from`` is a keyword in Python, it can't be used
|
|
89
|
+
as a keyword argument. Instead, ``from_`` can be passed, and
|
|
90
|
+
R will recognize it as the correct thing::
|
|
91
|
+
|
|
92
|
+
sage: r.seq(length=10, from_=-1, by=.2)
|
|
93
|
+
[1] -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4 0.6 0.8
|
|
94
|
+
|
|
95
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
96
|
+
sage: x.rep(2)
|
|
97
|
+
[1] 10.4 5.6 3.1 6.4 21.7 10.4 5.6 3.1 6.4 21.7
|
|
98
|
+
sage: x.rep(times=2)
|
|
99
|
+
[1] 10.4 5.6 3.1 6.4 21.7 10.4 5.6 3.1 6.4 21.7
|
|
100
|
+
sage: x.rep(each=2)
|
|
101
|
+
[1] 10.4 10.4 5.6 5.6 3.1 3.1 6.4 6.4 21.7 21.7
|
|
102
|
+
|
|
103
|
+
Missing Values::
|
|
104
|
+
|
|
105
|
+
sage: na = r('NA')
|
|
106
|
+
sage: z = r([1,2,3,na])
|
|
107
|
+
sage: z
|
|
108
|
+
[1] 1 2 3 NA
|
|
109
|
+
sage: ind = r.is_na(z)
|
|
110
|
+
sage: ind
|
|
111
|
+
[1] FALSE FALSE FALSE TRUE
|
|
112
|
+
sage: zero = r(0)
|
|
113
|
+
sage: zero / zero
|
|
114
|
+
[1] NaN
|
|
115
|
+
sage: inf = r('Inf')
|
|
116
|
+
sage: inf-inf
|
|
117
|
+
[1] NaN
|
|
118
|
+
sage: r.is_na(inf)
|
|
119
|
+
[1] FALSE
|
|
120
|
+
sage: r.is_na(inf-inf)
|
|
121
|
+
[1] TRUE
|
|
122
|
+
sage: r.is_na(zero/zero)
|
|
123
|
+
[1] TRUE
|
|
124
|
+
sage: r.is_na(na)
|
|
125
|
+
[1] TRUE
|
|
126
|
+
sage: r.is_nan(inf-inf)
|
|
127
|
+
[1] TRUE
|
|
128
|
+
sage: r.is_nan(zero/zero)
|
|
129
|
+
[1] TRUE
|
|
130
|
+
sage: r.is_nan(na)
|
|
131
|
+
[1] FALSE
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
Character Vectors::
|
|
135
|
+
|
|
136
|
+
sage: labs = r.paste('c("X","Y")', '1:10', sep='""'); labs
|
|
137
|
+
[1] "X1" "Y2" "X3" "Y4" "X5" "Y6" "X7" "Y8" "X9" "Y10"
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
Index vectors; selecting and modifying subsets of a data set::
|
|
141
|
+
|
|
142
|
+
sage: na = r('NA')
|
|
143
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7,na]); x
|
|
144
|
+
[1] 10.4 5.6 3.1 6.4 21.7 NA
|
|
145
|
+
sage: x['!is.na(self)']
|
|
146
|
+
[1] 10.4 5.6 3.1 6.4 21.7
|
|
147
|
+
|
|
148
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7,na]); x
|
|
149
|
+
[1] 10.4 5.6 3.1 6.4 21.7 NA
|
|
150
|
+
sage: (x+1)['(!is.na(self)) & self>0']
|
|
151
|
+
[1] 11.4 6.6 4.1 7.4 22.7
|
|
152
|
+
sage: x = r([10.4,-2,3.1,-0.5,21.7,na]); x
|
|
153
|
+
[1] 10.4 -2.0 3.1 -0.5 21.7 NA
|
|
154
|
+
sage: (x+1)['(!is.na(self)) & self>0']
|
|
155
|
+
[1] 11.4 4.1 0.5 22.7
|
|
156
|
+
|
|
157
|
+
Distributions::
|
|
158
|
+
|
|
159
|
+
sage: r.options(width='60')
|
|
160
|
+
$width
|
|
161
|
+
[1] 80
|
|
162
|
+
|
|
163
|
+
sage: rr = r.dnorm(r.seq(-3,3,0.1))
|
|
164
|
+
sage: rr
|
|
165
|
+
[1] 0.004431848 0.005952532 0.007915452 0.010420935
|
|
166
|
+
[5] 0.013582969 0.017528300 0.022394530 0.028327038
|
|
167
|
+
[9] 0.035474593 0.043983596 0.053990967 0.065615815
|
|
168
|
+
[13] 0.078950158 0.094049077 0.110920835 0.129517596
|
|
169
|
+
[17] 0.149727466 0.171368592 0.194186055 0.217852177
|
|
170
|
+
[21] 0.241970725 0.266085250 0.289691553 0.312253933
|
|
171
|
+
[25] 0.333224603 0.352065327 0.368270140 0.381387815
|
|
172
|
+
[29] 0.391042694 0.396952547 0.398942280 0.396952547
|
|
173
|
+
[33] 0.391042694 0.381387815 0.368270140 0.352065327
|
|
174
|
+
[37] 0.333224603 0.312253933 0.289691553 0.266085250
|
|
175
|
+
[41] 0.241970725 0.217852177 0.194186055 0.171368592
|
|
176
|
+
[45] 0.149727466 0.129517596 0.110920835 0.094049077
|
|
177
|
+
[49] 0.078950158 0.065615815 0.053990967 0.043983596
|
|
178
|
+
[53] 0.035474593 0.028327038 0.022394530 0.017528300
|
|
179
|
+
[57] 0.013582969 0.010420935 0.007915452 0.005952532
|
|
180
|
+
[61] 0.004431848
|
|
181
|
+
|
|
182
|
+
Convert R Data Structures to Python/Sage::
|
|
183
|
+
|
|
184
|
+
sage: rr = r.dnorm(r.seq(-3,3,0.1))
|
|
185
|
+
sage: sum(rr._sage_())
|
|
186
|
+
9.9772125168981...
|
|
187
|
+
|
|
188
|
+
Or you get a dictionary to be able to access all the information::
|
|
189
|
+
|
|
190
|
+
sage: rs = r.summary(r.c(1,4,3,4,3,2,5,1))
|
|
191
|
+
sage: rs
|
|
192
|
+
Min. 1st Qu. Median Mean 3rd Qu. Max.
|
|
193
|
+
1.000 1.750 3.000 2.875 4.000 5.000
|
|
194
|
+
sage: d = rs._sage_()
|
|
195
|
+
sage: d['DATA']
|
|
196
|
+
[1, 1.75, 3, 2.875, 4, 5]
|
|
197
|
+
sage: d['_Names']
|
|
198
|
+
['Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.']
|
|
199
|
+
sage: d['_r_class']
|
|
200
|
+
['summaryDefault', 'table']
|
|
201
|
+
|
|
202
|
+
It is also possible to access the plotting capabilities of R
|
|
203
|
+
through Sage. For more information see the documentation of
|
|
204
|
+
r.plot() or r.png().
|
|
205
|
+
|
|
206
|
+
THE JUPYTER NOTEBOOK INTERFACE (work in progress).
|
|
207
|
+
|
|
208
|
+
The %r interface described in the Sage notebook manual is not useful
|
|
209
|
+
in the Jupyter notebook : it creates a inferior R interpreter which
|
|
210
|
+
cannot be escaped.
|
|
211
|
+
|
|
212
|
+
The RPy2 library allows the creation of an R cell in the Jupyter
|
|
213
|
+
notebook analogous to the %r escape in command line or %r cell in a
|
|
214
|
+
Sage notebook.
|
|
215
|
+
|
|
216
|
+
The interface is loaded by a cell containing the sole code:
|
|
217
|
+
|
|
218
|
+
"%load_ext rpy2.ipython"
|
|
219
|
+
|
|
220
|
+
After execution of this code, the %R and %%R magics are available:
|
|
221
|
+
|
|
222
|
+
- %R allows the execution of a single line of R code. Data exchange is
|
|
223
|
+
possible via the -i and -o options. Do "%R?" in a standalone cell
|
|
224
|
+
to get the documentation.
|
|
225
|
+
|
|
226
|
+
- %%R allows the execution in R of the whole text of a cell, with
|
|
227
|
+
similar options (do "%%R?" in a standalone cell for
|
|
228
|
+
documentation).
|
|
229
|
+
|
|
230
|
+
A few important points must be noted:
|
|
231
|
+
|
|
232
|
+
- The R interpreter launched by this interface IS (currently)
|
|
233
|
+
DIFFERENT from the R interpreter used br other r... functions.
|
|
234
|
+
|
|
235
|
+
- Data exchanged via the -i and -o options have a format DIFFERENT
|
|
236
|
+
from the format used by the r... functions (RPy2 mostly uses arrays,
|
|
237
|
+
and bugs the user to use the pandas Python package).
|
|
238
|
+
|
|
239
|
+
- R graphics are (beautifully) displayed in output cells, but are not
|
|
240
|
+
directly importable. You have to save them as .png, .pdf or .svg
|
|
241
|
+
files and import them in Sage for further use.
|
|
242
|
+
|
|
243
|
+
In its current incarnation, this interface is mostly useful to
|
|
244
|
+
statisticians needing Sage for a few symbolic computations but mostly
|
|
245
|
+
using R for applied work.
|
|
246
|
+
|
|
247
|
+
AUTHORS:
|
|
248
|
+
|
|
249
|
+
- Mike Hansen (2007-11-01)
|
|
250
|
+
- William Stein (2008-04-19)
|
|
251
|
+
- Harald Schilly (2008-03-20)
|
|
252
|
+
- Mike Hansen (2008-04-19)
|
|
253
|
+
- Emmanuel Charpentier (2015-12-12, RPy2 interface)
|
|
254
|
+
"""
|
|
255
|
+
|
|
256
|
+
# ************************************************************************
|
|
257
|
+
#
|
|
258
|
+
# Copyright (C) 2007 William Stein <wstein@gmail.com>
|
|
259
|
+
# 2007 Mike Hansen <mhansen@gmail.com>
|
|
260
|
+
# 2008 Harald Schilly <harald.schilly@gmail.com>
|
|
261
|
+
#
|
|
262
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
263
|
+
#
|
|
264
|
+
# https://www.gnu.org/licenses/
|
|
265
|
+
#
|
|
266
|
+
# ************************************************************************
|
|
267
|
+
import os
|
|
268
|
+
|
|
269
|
+
from .interface import Interface, InterfaceElement, InterfaceFunction, InterfaceFunctionElement
|
|
270
|
+
from sage.env import DOT_SAGE
|
|
271
|
+
import re
|
|
272
|
+
from sage.structure.element import parent
|
|
273
|
+
from sage.interfaces.tab_completion import ExtraTabCompletion
|
|
274
|
+
from sage.misc.instancedoc import instancedoc
|
|
275
|
+
|
|
276
|
+
# see the _lazy_init for some reasoning behind the lazy imports
|
|
277
|
+
from sage.misc.lazy_import import lazy_import
|
|
278
|
+
from sage.features import PythonModule
|
|
279
|
+
|
|
280
|
+
rpy2_feature = PythonModule('rpy2', spkg='rpy2', type='standard')
|
|
281
|
+
|
|
282
|
+
lazy_import("rpy2", "robjects", feature=rpy2_feature)
|
|
283
|
+
lazy_import("rpy2.robjects", "packages", "rpy2_packages", feature=rpy2_feature)
|
|
284
|
+
lazy_import("rpy2.robjects.conversion", ["localconverter", "Converter"], feature=rpy2_feature)
|
|
285
|
+
|
|
286
|
+
# for help page fetching
|
|
287
|
+
lazy_import("rpy2.robjects.help", "Package", feature=rpy2_feature)
|
|
288
|
+
lazy_import("rpy2", "rinterface", feature=rpy2_feature)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
COMMANDS_CACHE = '%s/r_commandlist.sobj' % DOT_SAGE
|
|
292
|
+
|
|
293
|
+
# there is a mirror network, but lets take #1 for now
|
|
294
|
+
RRepositoryURL = "http://cran.r-project.org/"
|
|
295
|
+
RFilteredPackages = ['.GlobalEnv']
|
|
296
|
+
|
|
297
|
+
# crosscheck with https://svn.r-project.org/R/trunk/src/main/names.c
|
|
298
|
+
# but package:base should cover this. i think.
|
|
299
|
+
RBaseCommands = ['c', "NULL", "NA", "True", "False", "Inf", "NaN"]
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def _setup_r_to_sage_converter():
|
|
303
|
+
"""
|
|
304
|
+
Set up a the converter used to convert from rpy2's
|
|
305
|
+
representation of R objects to the one sage expects.
|
|
306
|
+
|
|
307
|
+
EXAMPLES:
|
|
308
|
+
|
|
309
|
+
Simple numeric values are represented as vectors in R. So `1`
|
|
310
|
+
would actually be an array of length 1. We convert all vectors of
|
|
311
|
+
length 1 to simple values, whether or not they "originally" were
|
|
312
|
+
simple values or not::
|
|
313
|
+
|
|
314
|
+
sage: r([42]).sage()
|
|
315
|
+
42
|
|
316
|
+
|
|
317
|
+
sage: r(42).sage()
|
|
318
|
+
42
|
|
319
|
+
|
|
320
|
+
sage: r('c("foo")').sage()
|
|
321
|
+
'foo'
|
|
322
|
+
|
|
323
|
+
Arrays of length greater than one are treated normally::
|
|
324
|
+
|
|
325
|
+
sage: r([42, 43]).sage()
|
|
326
|
+
[42, 43]
|
|
327
|
+
|
|
328
|
+
We also convert all numeric values to integers if that is possible without
|
|
329
|
+
loss of precision::
|
|
330
|
+
|
|
331
|
+
sage: type(r([1.0]).sage()) == int
|
|
332
|
+
True
|
|
333
|
+
|
|
334
|
+
sage: r([1.0, 42.5]).sage()
|
|
335
|
+
[1, 42.5]
|
|
336
|
+
|
|
337
|
+
Matrices are converted to sage matrices::
|
|
338
|
+
|
|
339
|
+
sage: r('matrix(c(2,4,3,1,5,7), nrow=2, ncol=3)').sage()
|
|
340
|
+
[2 3 5]
|
|
341
|
+
[4 1 7]
|
|
342
|
+
|
|
343
|
+
More complex r structures are represented by dictionaries::
|
|
344
|
+
|
|
345
|
+
sage: r.summary(1).sage()
|
|
346
|
+
{'DATA': [1, 1, 1, 1, 1, 1],
|
|
347
|
+
'_Names': ['Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'],
|
|
348
|
+
'_r_class': ['summaryDefault', 'table']}
|
|
349
|
+
|
|
350
|
+
sage: r.options(width='60').sage()
|
|
351
|
+
{'DATA': {'width': 60}, '_Names': 'width'}
|
|
352
|
+
|
|
353
|
+
The conversion can handle "not a number", infinity, imaginary values and
|
|
354
|
+
missing values::
|
|
355
|
+
|
|
356
|
+
sage: r(-17).sqrt().sage()
|
|
357
|
+
nan
|
|
358
|
+
sage: r('-17+0i').sqrt().sage()
|
|
359
|
+
4.123105625617661j
|
|
360
|
+
sage: r('NA').sage()
|
|
361
|
+
NA
|
|
362
|
+
sage: inf = r('Inf'); inf.sage()
|
|
363
|
+
inf
|
|
364
|
+
|
|
365
|
+
Character Vectors are represented by regular python arrays::
|
|
366
|
+
|
|
367
|
+
sage: labs = r.paste('c("X","Y")', '1:10', sep='""'); labs.sage()
|
|
368
|
+
['X1', 'Y2', 'X3', 'Y4', 'X5', 'Y6', 'X7', 'Y8', 'X9', 'Y10']
|
|
369
|
+
"""
|
|
370
|
+
from rpy2.rinterface import SexpVector, ListSexpVector, FloatSexpVector
|
|
371
|
+
|
|
372
|
+
# convert rpy2's representation of r objects to the one sage expects (as defined by the old
|
|
373
|
+
# expect interface)
|
|
374
|
+
cv = Converter('r to sage converter')
|
|
375
|
+
|
|
376
|
+
# support rpy version 2 and 3
|
|
377
|
+
try:
|
|
378
|
+
rpy2py = cv.rpy2py
|
|
379
|
+
except AttributeError:
|
|
380
|
+
rpy2py = cv.ri2py
|
|
381
|
+
|
|
382
|
+
# fallback
|
|
383
|
+
rpy2py.register(object, lambda obj: obj)
|
|
384
|
+
|
|
385
|
+
def float_to_int_if_possible(f):
|
|
386
|
+
# First, round the float to at most 15 significant places.
|
|
387
|
+
# This is what R does by default when using `dput`. It prevents
|
|
388
|
+
# platform-specific fluctuations.
|
|
389
|
+
f = float('%.15g' % f)
|
|
390
|
+
# Preserve the behaviour of the old r parser, e.g. return 1 instead of 1.0
|
|
391
|
+
float_or_int = int(f) if isinstance(f, int) or f.is_integer() else f
|
|
392
|
+
return float_or_int
|
|
393
|
+
rpy2py.register(float, float_to_int_if_possible)
|
|
394
|
+
|
|
395
|
+
def list_to_singleton_if_possible(l):
|
|
396
|
+
if len(l) == 1:
|
|
397
|
+
return l[0]
|
|
398
|
+
else:
|
|
399
|
+
return l
|
|
400
|
+
|
|
401
|
+
def _vector(vec):
|
|
402
|
+
attrs = vec.list_attrs()
|
|
403
|
+
# Recursive calls have to be made explicitly
|
|
404
|
+
# https://bitbucket.org/rpy2/rpy2/issues/363/custom-converters-are-not-applied
|
|
405
|
+
data = list_to_singleton_if_possible([rpy2py(val) for val in vec])
|
|
406
|
+
rclass = list(vec.do_slot('class')) if 'class' in attrs else vec.rclass
|
|
407
|
+
|
|
408
|
+
if 'names' in attrs:
|
|
409
|
+
# separate names and values, call rpy2py recursively to convert elements
|
|
410
|
+
names = list_to_singleton_if_possible(list(vec.do_slot('names')))
|
|
411
|
+
return {
|
|
412
|
+
'DATA': data,
|
|
413
|
+
'_Names': names,
|
|
414
|
+
'_r_class': rclass,
|
|
415
|
+
}
|
|
416
|
+
else:
|
|
417
|
+
# if no names are present, convert to a normal list or a single value
|
|
418
|
+
return data
|
|
419
|
+
rpy2py.register(SexpVector, _vector)
|
|
420
|
+
|
|
421
|
+
def _matrix(mat):
|
|
422
|
+
if 'dim' in mat.list_attrs():
|
|
423
|
+
try:
|
|
424
|
+
from sage.matrix.constructor import matrix
|
|
425
|
+
dimensions = mat.do_slot("dim")
|
|
426
|
+
if len(dimensions) != 2:
|
|
427
|
+
raise NotImplementedError("Higher-dimension matrices are currently not supported")
|
|
428
|
+
(nrow, ncol) = dimensions
|
|
429
|
+
# Since R does it the other way round, we assign transposed and
|
|
430
|
+
# then transpose the matrix :)
|
|
431
|
+
m = matrix(ncol, nrow, [rpy2py(i) for i in mat])
|
|
432
|
+
return m.transpose()
|
|
433
|
+
except TypeError:
|
|
434
|
+
pass
|
|
435
|
+
else:
|
|
436
|
+
return _vector(mat)
|
|
437
|
+
rpy2py.register(FloatSexpVector, _matrix)
|
|
438
|
+
|
|
439
|
+
def _list_vector(vec):
|
|
440
|
+
# we have a R list (vector of arbitrary elements)
|
|
441
|
+
attrs = vec.list_attrs()
|
|
442
|
+
names = vec.do_slot('names')
|
|
443
|
+
values = [rpy2py(val) for val in vec]
|
|
444
|
+
rclass = list(vec.do_slot('class')) if 'class' in attrs else vec.rclass
|
|
445
|
+
data = zip(names, values)
|
|
446
|
+
return {
|
|
447
|
+
'DATA': dict(data),
|
|
448
|
+
'_Names': rpy2py(names),
|
|
449
|
+
# We don't give the rclass here because the old expect interface
|
|
450
|
+
# didn't do that either and we want to maintain compatibility.
|
|
451
|
+
}
|
|
452
|
+
rpy2py.register(ListSexpVector, _list_vector)
|
|
453
|
+
|
|
454
|
+
return cv
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
class R(ExtraTabCompletion, Interface):
|
|
458
|
+
def __init__(self,
|
|
459
|
+
maxread=None,
|
|
460
|
+
logfile=None,
|
|
461
|
+
init_list_length=1024,
|
|
462
|
+
seed=None):
|
|
463
|
+
"""
|
|
464
|
+
An interface to the R interpreter.
|
|
465
|
+
|
|
466
|
+
R is a comprehensive collection of methods for statistics,
|
|
467
|
+
modelling, bioinformatics, data analysis and much more.
|
|
468
|
+
For more details, see http://www.r-project.org/about.html
|
|
469
|
+
|
|
470
|
+
Resources:
|
|
471
|
+
|
|
472
|
+
* http://r-project.org/ provides more information about R.
|
|
473
|
+
* http://rseek.org/ R's own search engine.
|
|
474
|
+
|
|
475
|
+
EXAMPLES::
|
|
476
|
+
|
|
477
|
+
sage: r.summary(r.c(1,2,3,111,2,3,2,3,2,5,4))
|
|
478
|
+
Min. 1st Qu. Median Mean 3rd Qu. Max.
|
|
479
|
+
1.00 2.00 3.00 12.55 3.50 111.00
|
|
480
|
+
|
|
481
|
+
TESTS::
|
|
482
|
+
|
|
483
|
+
sage: r == loads(dumps(r))
|
|
484
|
+
True
|
|
485
|
+
"""
|
|
486
|
+
Interface.__init__(
|
|
487
|
+
self,
|
|
488
|
+
name='r', # The capitalized version of this is used for printing.
|
|
489
|
+
)
|
|
490
|
+
self._seed = seed
|
|
491
|
+
self._initialized = False # done lazily
|
|
492
|
+
|
|
493
|
+
def _lazy_init(self):
|
|
494
|
+
"""
|
|
495
|
+
Initialize the R interpreter.
|
|
496
|
+
|
|
497
|
+
This will set the initial options and implicitly (through
|
|
498
|
+
lazy_import) import rpy2 if it is not already imported.
|
|
499
|
+
|
|
500
|
+
Importing rpy2 takes something in the order of hundreds of milliseconds.
|
|
501
|
+
It also takes tens of megabytes of RAM. Since an instance of R is
|
|
502
|
+
assigned to the global variable `r` at sage startup, it is important to
|
|
503
|
+
be as lazy as possible here.
|
|
504
|
+
For some discussion, see https://bitbucket.org/rpy2/rpy2/issues/490.
|
|
505
|
+
|
|
506
|
+
Also, importing rpy2 too early (e.g. before numpy) can cause issues with
|
|
507
|
+
the blas implementation that is used.
|
|
508
|
+
For details, see https://bitbucket.org/rpy2/rpy2/issues/491.
|
|
509
|
+
|
|
510
|
+
TESTS:
|
|
511
|
+
|
|
512
|
+
Initialization happens on eval::
|
|
513
|
+
|
|
514
|
+
sage: my_r = R()
|
|
515
|
+
sage: my_r._initialized
|
|
516
|
+
False
|
|
517
|
+
sage: my_r(42) # indirect doctest
|
|
518
|
+
[1] 42
|
|
519
|
+
sage: my_r._initialized
|
|
520
|
+
True
|
|
521
|
+
|
|
522
|
+
And on package import::
|
|
523
|
+
|
|
524
|
+
sage: my_r = R()
|
|
525
|
+
sage: my_r._initialized
|
|
526
|
+
False
|
|
527
|
+
sage: my_r.library('grid')
|
|
528
|
+
sage: my_r._initialized
|
|
529
|
+
True
|
|
530
|
+
|
|
531
|
+
And when fetching help pages::
|
|
532
|
+
|
|
533
|
+
sage: my_r = R()
|
|
534
|
+
sage: my_r._initialized
|
|
535
|
+
False
|
|
536
|
+
sage: _ = my_r.help('c')
|
|
537
|
+
sage: my_r._initialized
|
|
538
|
+
True
|
|
539
|
+
"""
|
|
540
|
+
if not self._initialized:
|
|
541
|
+
# Set this to True *before* the call to start, since that will call eval() which will in turn call this function.
|
|
542
|
+
# Setting this to True early prevents infinite recursion.
|
|
543
|
+
self._initialized = True
|
|
544
|
+
self._r_to_sage_converter = _setup_r_to_sage_converter()
|
|
545
|
+
self._start()
|
|
546
|
+
|
|
547
|
+
def _coerce_impl(self, x, use_special=True):
|
|
548
|
+
"""
|
|
549
|
+
TESTS:
|
|
550
|
+
|
|
551
|
+
Check conversion of Booleans (:issue:`28705`)::
|
|
552
|
+
|
|
553
|
+
sage: repr(r(True)) == r._true_symbol() # indirect doctest
|
|
554
|
+
True
|
|
555
|
+
"""
|
|
556
|
+
# We overwrite _coerce_impl here because r._true_symbol() and
|
|
557
|
+
# r._false_symbol() are output strings that start with "[1] " and thus
|
|
558
|
+
# cannot be used as input
|
|
559
|
+
if isinstance(x, bool):
|
|
560
|
+
return self('TRUE' if x else 'FALSE')
|
|
561
|
+
return super()._coerce_impl(x, use_special=use_special)
|
|
562
|
+
|
|
563
|
+
def set_seed(self, seed=None):
|
|
564
|
+
"""
|
|
565
|
+
Set the seed for R interpreter.
|
|
566
|
+
|
|
567
|
+
The seed should be an integer.
|
|
568
|
+
|
|
569
|
+
EXAMPLES::
|
|
570
|
+
|
|
571
|
+
sage: r = R()
|
|
572
|
+
sage: r.set_seed(1)
|
|
573
|
+
1
|
|
574
|
+
sage: r.sample("1:10", 5) # random
|
|
575
|
+
[1] 3 4 5 7 2
|
|
576
|
+
"""
|
|
577
|
+
if seed is None:
|
|
578
|
+
seed = self.rand_seed()
|
|
579
|
+
self.eval('set.seed(%d)' % seed)
|
|
580
|
+
self._seed = seed
|
|
581
|
+
return seed
|
|
582
|
+
|
|
583
|
+
def _start(self):
|
|
584
|
+
"""
|
|
585
|
+
Start up the R interpreter and sets the initial prompt and options.
|
|
586
|
+
|
|
587
|
+
This is called the first time the R interface is actually used.
|
|
588
|
+
|
|
589
|
+
EXAMPLES::
|
|
590
|
+
|
|
591
|
+
sage: r = R()
|
|
592
|
+
sage: r._start()
|
|
593
|
+
"""
|
|
594
|
+
# pager needed to replace help view from less to printout
|
|
595
|
+
# option device= is for plotting, is set to x11, NULL would be better?
|
|
596
|
+
self.eval('options(pager="cat",device="png")')
|
|
597
|
+
self.eval('options(repos="%s")' % RRepositoryURL)
|
|
598
|
+
self.eval('options(CRAN="%s")' % RRepositoryURL)
|
|
599
|
+
|
|
600
|
+
# don't abort on errors, just raise them!
|
|
601
|
+
# necessary for non-interactive execution
|
|
602
|
+
self.eval('options(error = expression(NULL))')
|
|
603
|
+
|
|
604
|
+
# set random seed
|
|
605
|
+
self.set_seed(self._seed)
|
|
606
|
+
|
|
607
|
+
def png(self, *args, **kwds):
|
|
608
|
+
"""
|
|
609
|
+
Create an R PNG device.
|
|
610
|
+
|
|
611
|
+
This should primarily be used to save an R graphic to a custom file. Note
|
|
612
|
+
that when using this in the notebook, one must plot in the same cell that
|
|
613
|
+
one creates the device. See r.plot() documentation for more information
|
|
614
|
+
about plotting via R in Sage.
|
|
615
|
+
|
|
616
|
+
These examples won't work on the many platforms where R still gets
|
|
617
|
+
built without graphics support.
|
|
618
|
+
|
|
619
|
+
EXAMPLES::
|
|
620
|
+
|
|
621
|
+
sage: filename = tmp_filename() + '.png'
|
|
622
|
+
sage: r.png(filename='"%s"'%filename) # optional - rgraphics
|
|
623
|
+
NULL
|
|
624
|
+
sage: x = r([1,2,3])
|
|
625
|
+
sage: y = r([4,5,6])
|
|
626
|
+
sage: r.plot(x,y) # optional - rgraphics
|
|
627
|
+
null device
|
|
628
|
+
1
|
|
629
|
+
sage: import os; os.unlink(filename) # optional - rgraphics
|
|
630
|
+
|
|
631
|
+
We want to make sure that we actually can view R graphics, which happens
|
|
632
|
+
differently on different platforms::
|
|
633
|
+
|
|
634
|
+
sage: s = r.eval('capabilities("png")') # should be on Linux and Solaris
|
|
635
|
+
sage: t = r.eval('capabilities("aqua")') # should be on all supported Mac versions
|
|
636
|
+
sage: "TRUE" in s+t # optional - rgraphics
|
|
637
|
+
True
|
|
638
|
+
"""
|
|
639
|
+
# Check to see if R has PNG support
|
|
640
|
+
s = self.eval('capabilities("png")')
|
|
641
|
+
t = self.eval('capabilities("aqua")')
|
|
642
|
+
if "TRUE" not in s + t:
|
|
643
|
+
raise RuntimeError("R was not compiled with PNG support")
|
|
644
|
+
return RFunction(self, 'png')(*args, **kwds)
|
|
645
|
+
|
|
646
|
+
def convert_r_list(self, l):
|
|
647
|
+
r"""
|
|
648
|
+
Convert an R list to a Python list.
|
|
649
|
+
|
|
650
|
+
EXAMPLES::
|
|
651
|
+
|
|
652
|
+
sage: s = 'c(".GlobalEnv", "package:stats", "package:graphics", "package:grDevices", \n"package:utils", "package:datasets", "package:methods", "Autoloads", \n"package:base")'
|
|
653
|
+
sage: r.convert_r_list(s)
|
|
654
|
+
['.GlobalEnv',
|
|
655
|
+
'package:stats',
|
|
656
|
+
'package:graphics',
|
|
657
|
+
'package:grDevices',
|
|
658
|
+
'package:utils',
|
|
659
|
+
'package:datasets',
|
|
660
|
+
'package:methods',
|
|
661
|
+
'Autoloads',
|
|
662
|
+
'package:base']
|
|
663
|
+
"""
|
|
664
|
+
# This function is only kept for legacy reasons. It was used internally
|
|
665
|
+
# in the old expect based interface and for some reason was made part
|
|
666
|
+
# of the public api.
|
|
667
|
+
return self(l).sage()
|
|
668
|
+
|
|
669
|
+
def install_packages(self, package_name):
|
|
670
|
+
"""
|
|
671
|
+
Install an R package into Sage's R installation.
|
|
672
|
+
|
|
673
|
+
EXAMPLES::
|
|
674
|
+
|
|
675
|
+
sage: r.install_packages('aaMI') # not tested
|
|
676
|
+
...
|
|
677
|
+
R is free software and comes with ABSOLUTELY NO WARRANTY.
|
|
678
|
+
You are welcome to redistribute it under certain conditions.
|
|
679
|
+
Type 'license()' or 'licence()' for distribution details.
|
|
680
|
+
...
|
|
681
|
+
Please restart Sage in order to use 'aaMI'.
|
|
682
|
+
"""
|
|
683
|
+
cmd = """options(repos="%s"); install.packages("%s")""" % (RRepositoryURL, package_name)
|
|
684
|
+
os.system("time echo '%s' | R --vanilla" % cmd)
|
|
685
|
+
print("Please restart Sage in order to use '%s'." % package_name)
|
|
686
|
+
|
|
687
|
+
def _repr_(self):
|
|
688
|
+
"""
|
|
689
|
+
Return string representation of this R interface.
|
|
690
|
+
|
|
691
|
+
EXAMPLES::
|
|
692
|
+
|
|
693
|
+
sage: r # indirect doctest
|
|
694
|
+
R Interpreter
|
|
695
|
+
"""
|
|
696
|
+
return 'R Interpreter'
|
|
697
|
+
|
|
698
|
+
def __reduce__(self):
|
|
699
|
+
"""
|
|
700
|
+
Used in serializing an R interface.
|
|
701
|
+
|
|
702
|
+
EXAMPLES::
|
|
703
|
+
|
|
704
|
+
sage: from sage.interfaces.r import r
|
|
705
|
+
sage: rlr, t = r.__reduce__()
|
|
706
|
+
sage: rlr(*t)
|
|
707
|
+
R Interpreter
|
|
708
|
+
"""
|
|
709
|
+
return reduce_load_R, tuple([])
|
|
710
|
+
|
|
711
|
+
def __getattr__(self, attrname):
|
|
712
|
+
"""
|
|
713
|
+
Called when you get an attribute of the R interface. This
|
|
714
|
+
manufactures an R function, which is a Python function that
|
|
715
|
+
can then be called with various inputs.
|
|
716
|
+
|
|
717
|
+
EXAMPLES::
|
|
718
|
+
|
|
719
|
+
sage: c = r.c; c
|
|
720
|
+
c
|
|
721
|
+
sage: type(c)
|
|
722
|
+
<class 'sage.interfaces.r.RFunction'>
|
|
723
|
+
"""
|
|
724
|
+
try:
|
|
725
|
+
# First try to get a regular python attribute. This makes it
|
|
726
|
+
# possible to still use attributes like _r_to_sage_converter
|
|
727
|
+
# internally.
|
|
728
|
+
self.__getattribute__(attrname)
|
|
729
|
+
except AttributeError:
|
|
730
|
+
# if there is no such attribute, get the r attribute
|
|
731
|
+
if attrname[:1] == "_":
|
|
732
|
+
raise AttributeError("Attribute {} is not allowed to start with an underscore.".format(attrname))
|
|
733
|
+
return RFunction(self, attrname)
|
|
734
|
+
|
|
735
|
+
def _read_in_file_command(self, filename):
|
|
736
|
+
r"""
|
|
737
|
+
Return the R command (as a string) to read in a file named
|
|
738
|
+
filename into the R interpreter.
|
|
739
|
+
|
|
740
|
+
EXAMPLES::
|
|
741
|
+
|
|
742
|
+
sage: r._read_in_file_command('file.txt')
|
|
743
|
+
'file=file("file.txt",open="r")\nsource(file)'
|
|
744
|
+
"""
|
|
745
|
+
return 'file=file("%s",open="r")\nsource(file)' % filename
|
|
746
|
+
|
|
747
|
+
def read(self, filename):
|
|
748
|
+
r"""
|
|
749
|
+
Read filename into the R interpreter by calling R's source function on a
|
|
750
|
+
read-only file connection.
|
|
751
|
+
|
|
752
|
+
EXAMPLES::
|
|
753
|
+
|
|
754
|
+
sage: filename = tmp_filename()
|
|
755
|
+
sage: f = open(filename, 'w')
|
|
756
|
+
sage: _ = f.write('a <- 2+2\n')
|
|
757
|
+
sage: f.close()
|
|
758
|
+
sage: r.read(filename)
|
|
759
|
+
sage: r.get('a')
|
|
760
|
+
'[1] 4'
|
|
761
|
+
"""
|
|
762
|
+
self.eval(self._read_in_file_command(filename))
|
|
763
|
+
|
|
764
|
+
def _install_hints(self):
|
|
765
|
+
"""
|
|
766
|
+
EXAMPLES::
|
|
767
|
+
|
|
768
|
+
sage: print(r._install_hints())
|
|
769
|
+
R is currently installed with Sage.
|
|
770
|
+
"""
|
|
771
|
+
return "R is currently installed with Sage.\n"
|
|
772
|
+
|
|
773
|
+
def _source(self, s):
|
|
774
|
+
"""
|
|
775
|
+
Return the source code of an R function as a string.
|
|
776
|
+
|
|
777
|
+
INPUT:
|
|
778
|
+
|
|
779
|
+
- ``s`` -- the name of the function as a string
|
|
780
|
+
|
|
781
|
+
EXAMPLES::
|
|
782
|
+
|
|
783
|
+
sage: print(r._source("c"))
|
|
784
|
+
function (...) .Primitive("c")
|
|
785
|
+
"""
|
|
786
|
+
if s[-2:] == "()":
|
|
787
|
+
s = s[-2:]
|
|
788
|
+
return self.eval('%s' % s)
|
|
789
|
+
|
|
790
|
+
def source(self, s):
|
|
791
|
+
"""
|
|
792
|
+
Display the R source (if possible) about the function named s.
|
|
793
|
+
|
|
794
|
+
INPUT:
|
|
795
|
+
|
|
796
|
+
- ``s`` -- string representing the function whose source code you want to see
|
|
797
|
+
|
|
798
|
+
OUTPUT: string; source code
|
|
799
|
+
|
|
800
|
+
EXAMPLES::
|
|
801
|
+
|
|
802
|
+
sage: print(r.source("c"))
|
|
803
|
+
function (...) .Primitive("c")
|
|
804
|
+
"""
|
|
805
|
+
return self._source(s)
|
|
806
|
+
|
|
807
|
+
def version(self):
|
|
808
|
+
"""
|
|
809
|
+
Return the version of R currently running.
|
|
810
|
+
|
|
811
|
+
OUTPUT: tuple of ints; string
|
|
812
|
+
|
|
813
|
+
EXAMPLES::
|
|
814
|
+
|
|
815
|
+
sage: r.version() # not tested
|
|
816
|
+
((3, 0, 1), 'R version 3.0.1 (2013-05-16)')
|
|
817
|
+
sage: rint, rstr = r.version()
|
|
818
|
+
sage: rint[0] >= 3
|
|
819
|
+
True
|
|
820
|
+
sage: rstr.startswith('R version')
|
|
821
|
+
True
|
|
822
|
+
"""
|
|
823
|
+
major_re = re.compile(r'^major\s*(\d.*?)$', re.M)
|
|
824
|
+
minor_re = re.compile(r'^minor\s*(\d.*?)$', re.M)
|
|
825
|
+
version_string_re = re.compile(r'^version.string\s*(R.*?)$', re.M)
|
|
826
|
+
|
|
827
|
+
s = self.eval('version')
|
|
828
|
+
|
|
829
|
+
major = int(major_re.findall(s)[0].strip())
|
|
830
|
+
minor = tuple(int(i) for i in minor_re.findall(s)[0].strip().split("."))
|
|
831
|
+
version_string = version_string_re.findall(s)[0].strip()
|
|
832
|
+
|
|
833
|
+
return ((major,) + minor, version_string)
|
|
834
|
+
|
|
835
|
+
def library(self, library_name):
|
|
836
|
+
"""
|
|
837
|
+
Load the library library_name into the R interpreter.
|
|
838
|
+
|
|
839
|
+
This function raises an :exc:`ImportError` if the given library
|
|
840
|
+
is not known.
|
|
841
|
+
|
|
842
|
+
INPUT:
|
|
843
|
+
|
|
844
|
+
- ``library_name`` -- string
|
|
845
|
+
|
|
846
|
+
EXAMPLES::
|
|
847
|
+
|
|
848
|
+
sage: r.library('grid')
|
|
849
|
+
sage: 'grid' in r.eval('(.packages())')
|
|
850
|
+
True
|
|
851
|
+
sage: r.library('foobar')
|
|
852
|
+
Traceback (most recent call last):
|
|
853
|
+
...
|
|
854
|
+
ImportError: ...
|
|
855
|
+
"""
|
|
856
|
+
self._lazy_init()
|
|
857
|
+
if rpy2_packages.isinstalled(library_name):
|
|
858
|
+
rpy2_packages.importr(library_name)
|
|
859
|
+
else:
|
|
860
|
+
raise ImportError("R library {} not installed".format(library_name))
|
|
861
|
+
|
|
862
|
+
try:
|
|
863
|
+
# We need to rebuild keywords!
|
|
864
|
+
del self.__tab_completion
|
|
865
|
+
except AttributeError:
|
|
866
|
+
pass
|
|
867
|
+
self._tab_completion(verbose=False, use_disk_cache=False)
|
|
868
|
+
|
|
869
|
+
require = library # overwrites require
|
|
870
|
+
|
|
871
|
+
def available_packages(self):
|
|
872
|
+
"""
|
|
873
|
+
Return a list of all available R package names.
|
|
874
|
+
|
|
875
|
+
This list is not necessarily sorted.
|
|
876
|
+
|
|
877
|
+
OUTPUT: list of strings
|
|
878
|
+
|
|
879
|
+
.. NOTE::
|
|
880
|
+
|
|
881
|
+
This requires an internet connection. The CRAN server is
|
|
882
|
+
that is checked is defined at the top of sage/interfaces/r.py.
|
|
883
|
+
|
|
884
|
+
EXAMPLES::
|
|
885
|
+
|
|
886
|
+
sage: ap = r.available_packages() # optional - internet
|
|
887
|
+
sage: len(ap) > 20 # optional - internet
|
|
888
|
+
True
|
|
889
|
+
"""
|
|
890
|
+
p = self.new('available.packages("%s/src/contrib")' % RRepositoryURL)
|
|
891
|
+
s = str(p).splitlines()[1:]
|
|
892
|
+
v = [x.split()[0].strip("'") for x in s]
|
|
893
|
+
return v
|
|
894
|
+
# The following was more structural, but breaks on my machine. (stein)
|
|
895
|
+
# p = p._sage_()
|
|
896
|
+
# s = p['_Dim'][0]
|
|
897
|
+
# l = [[p['DATA'][i],p['DATA'][s+1+i]] for i in range(s)]
|
|
898
|
+
# return l
|
|
899
|
+
|
|
900
|
+
def _object_class(self):
|
|
901
|
+
"""
|
|
902
|
+
Return the underlying class of elements of the R interface object.
|
|
903
|
+
|
|
904
|
+
OUTPUT: a Python class
|
|
905
|
+
|
|
906
|
+
EXAMPLES::
|
|
907
|
+
|
|
908
|
+
sage: r._object_class()
|
|
909
|
+
<class 'sage.interfaces.r.RElement'>
|
|
910
|
+
"""
|
|
911
|
+
return RElement
|
|
912
|
+
|
|
913
|
+
def _true_symbol(self):
|
|
914
|
+
"""
|
|
915
|
+
Return the symbol that represents ``True`` in R.
|
|
916
|
+
|
|
917
|
+
OUTPUT: string
|
|
918
|
+
|
|
919
|
+
EXAMPLES::
|
|
920
|
+
|
|
921
|
+
sage: r._true_symbol()
|
|
922
|
+
'[1] TRUE'
|
|
923
|
+
"""
|
|
924
|
+
# return the string rep of truth, i.e., what the system outputs
|
|
925
|
+
# when you type 1==1.
|
|
926
|
+
return "[1] TRUE"
|
|
927
|
+
|
|
928
|
+
def _false_symbol(self):
|
|
929
|
+
"""
|
|
930
|
+
Return the symbol that represents ``True`` in R.
|
|
931
|
+
|
|
932
|
+
OUTPUT: string
|
|
933
|
+
|
|
934
|
+
EXAMPLES::
|
|
935
|
+
|
|
936
|
+
sage: r._false_symbol()
|
|
937
|
+
'[1] FALSE'
|
|
938
|
+
"""
|
|
939
|
+
# return the string rep of false, i.e., what the system outputs
|
|
940
|
+
# when you type 1==2.
|
|
941
|
+
return "[1] FALSE"
|
|
942
|
+
|
|
943
|
+
def _equality_symbol(self):
|
|
944
|
+
"""
|
|
945
|
+
EXAMPLES::
|
|
946
|
+
|
|
947
|
+
sage: r._equality_symbol()
|
|
948
|
+
'=='
|
|
949
|
+
"""
|
|
950
|
+
# return the symbol for checking equality, e.g., == or eq.
|
|
951
|
+
return "=="
|
|
952
|
+
|
|
953
|
+
# A replacement for rpy2's help.pages that only considers loaded packages
|
|
954
|
+
# (as R's help function does by default). Hopefully upstream will support
|
|
955
|
+
# this in the future: https://bitbucket.org/rpy2/rpy2/issues/498
|
|
956
|
+
def _loaded_package_pages(self, topic):
|
|
957
|
+
# for some reason `except` doesn't work with lazy import, so import this here
|
|
958
|
+
from rpy2.robjects.help import HelpNotFoundError
|
|
959
|
+
self._lazy_init()
|
|
960
|
+
res = list()
|
|
961
|
+
|
|
962
|
+
for name in rinterface.baseenv['loadedNamespaces']():
|
|
963
|
+
pack = Package(name)
|
|
964
|
+
try:
|
|
965
|
+
page = pack.fetch(topic)
|
|
966
|
+
res.append(page)
|
|
967
|
+
except HelpNotFoundError:
|
|
968
|
+
pass
|
|
969
|
+
|
|
970
|
+
return tuple(res)
|
|
971
|
+
|
|
972
|
+
def help(self, command):
|
|
973
|
+
"""
|
|
974
|
+
Return help string for a given command.
|
|
975
|
+
|
|
976
|
+
INPUT:
|
|
977
|
+
|
|
978
|
+
- ``command`` -- string
|
|
979
|
+
|
|
980
|
+
OUTPUT: HelpExpression; a subclass of string whose ``__repr__``
|
|
981
|
+
method is ``__str__``, so it prints nicely
|
|
982
|
+
|
|
983
|
+
EXAMPLES::
|
|
984
|
+
|
|
985
|
+
sage: r.help('c')
|
|
986
|
+
title
|
|
987
|
+
-----
|
|
988
|
+
<BLANKLINE>
|
|
989
|
+
Combine Values into a Vector or List
|
|
990
|
+
<BLANKLINE>
|
|
991
|
+
name
|
|
992
|
+
----
|
|
993
|
+
<BLANKLINE>
|
|
994
|
+
c
|
|
995
|
+
...
|
|
996
|
+
"""
|
|
997
|
+
# This is looking for the topic in all existing namespaces.
|
|
998
|
+
# Theoretically, there may be multiple options. We ignore that.
|
|
999
|
+
pages_for_topic = self._loaded_package_pages(command)
|
|
1000
|
+
if len(pages_for_topic) == 0:
|
|
1001
|
+
raise ValueError("There is no help page for the given topic")
|
|
1002
|
+
|
|
1003
|
+
s = pages_for_topic[0].to_docstring()
|
|
1004
|
+
return HelpExpression(s)
|
|
1005
|
+
|
|
1006
|
+
def _assign_symbol(self):
|
|
1007
|
+
"""
|
|
1008
|
+
Return the symbol used in R for assignment, which is ' <- '.
|
|
1009
|
+
|
|
1010
|
+
OUTPUT: string
|
|
1011
|
+
|
|
1012
|
+
EXAMPLES::
|
|
1013
|
+
|
|
1014
|
+
sage: r._assign_symbol()
|
|
1015
|
+
' <- '
|
|
1016
|
+
"""
|
|
1017
|
+
return " <- "
|
|
1018
|
+
|
|
1019
|
+
def _left_list_delim(self):
|
|
1020
|
+
"""
|
|
1021
|
+
Return the left delimiter for lists in R, which is 'c('.
|
|
1022
|
+
|
|
1023
|
+
OUTPUT: string
|
|
1024
|
+
|
|
1025
|
+
EXAMPLES::
|
|
1026
|
+
|
|
1027
|
+
sage: r._left_list_delim()
|
|
1028
|
+
'c('
|
|
1029
|
+
"""
|
|
1030
|
+
return "c("
|
|
1031
|
+
|
|
1032
|
+
def _right_list_delim(self):
|
|
1033
|
+
"""
|
|
1034
|
+
Return the right delimiter for lists in R, which is 'c('.
|
|
1035
|
+
|
|
1036
|
+
OUTPUT: string
|
|
1037
|
+
|
|
1038
|
+
EXAMPLES::
|
|
1039
|
+
|
|
1040
|
+
sage: r._right_list_delim()
|
|
1041
|
+
')'
|
|
1042
|
+
"""
|
|
1043
|
+
return ")"
|
|
1044
|
+
|
|
1045
|
+
def console(self):
|
|
1046
|
+
"""
|
|
1047
|
+
Run the R console as a separate new R process.
|
|
1048
|
+
|
|
1049
|
+
EXAMPLES::
|
|
1050
|
+
|
|
1051
|
+
sage: r.console() # not tested
|
|
1052
|
+
R version 2.6.1 (2007-11-26)
|
|
1053
|
+
Copyright (C) 2007 The R Foundation for Statistical Computing
|
|
1054
|
+
ISBN 3-900051-07-0
|
|
1055
|
+
...
|
|
1056
|
+
"""
|
|
1057
|
+
r_console()
|
|
1058
|
+
|
|
1059
|
+
def function_call(self, function, args=None, kwds=None):
|
|
1060
|
+
"""
|
|
1061
|
+
Return the result of calling an R function, with given args and keyword args.
|
|
1062
|
+
|
|
1063
|
+
OUTPUT: RElement; an object in R
|
|
1064
|
+
|
|
1065
|
+
EXAMPLES::
|
|
1066
|
+
|
|
1067
|
+
sage: r.function_call('length', args=[ [1,2,3] ])
|
|
1068
|
+
[1] 3
|
|
1069
|
+
"""
|
|
1070
|
+
args, kwds = self._convert_args_kwds(args, kwds)
|
|
1071
|
+
self._check_valid_function_name(function)
|
|
1072
|
+
return self.new("%s(%s)" % (function, ",".join([s.name() for s in args] +
|
|
1073
|
+
[self._sage_to_r_name(key) + '=' + kwds[key].name() for key in kwds])))
|
|
1074
|
+
|
|
1075
|
+
def call(self, function_name, *args, **kwds):
|
|
1076
|
+
r"""
|
|
1077
|
+
This is an alias for :meth:`function_call`.
|
|
1078
|
+
|
|
1079
|
+
EXAMPLES::
|
|
1080
|
+
|
|
1081
|
+
sage: r.call('length', [1,2,3])
|
|
1082
|
+
[1] 3
|
|
1083
|
+
"""
|
|
1084
|
+
return self.function_call(function_name, args=args, kwds=kwds)
|
|
1085
|
+
|
|
1086
|
+
def _an_element_(self):
|
|
1087
|
+
"""
|
|
1088
|
+
Return an element belonging to the R interpreter. This is used
|
|
1089
|
+
behind the scenes when doing things like comparisons, etc.
|
|
1090
|
+
|
|
1091
|
+
OUTPUT: RElement; an R element
|
|
1092
|
+
|
|
1093
|
+
EXAMPLES::
|
|
1094
|
+
|
|
1095
|
+
sage: r._an_element_()
|
|
1096
|
+
[1] 0
|
|
1097
|
+
sage: type(_)
|
|
1098
|
+
<class 'sage.interfaces.r.RElement'>
|
|
1099
|
+
"""
|
|
1100
|
+
return self(0)
|
|
1101
|
+
|
|
1102
|
+
def set(self, var, value):
|
|
1103
|
+
"""
|
|
1104
|
+
Set the variable var in R to what the string value evaluates to in R.
|
|
1105
|
+
|
|
1106
|
+
INPUT:
|
|
1107
|
+
|
|
1108
|
+
- ``var`` -- string
|
|
1109
|
+
- ``value`` -- string
|
|
1110
|
+
|
|
1111
|
+
EXAMPLES::
|
|
1112
|
+
|
|
1113
|
+
sage: r.set('a', '2 + 3')
|
|
1114
|
+
sage: r.get('a')
|
|
1115
|
+
'[1] 5'
|
|
1116
|
+
"""
|
|
1117
|
+
_ = self.eval(f'{var} <- {value}')
|
|
1118
|
+
|
|
1119
|
+
def get(self, var):
|
|
1120
|
+
"""
|
|
1121
|
+
Return the string representation of the variable var.
|
|
1122
|
+
|
|
1123
|
+
INPUT:
|
|
1124
|
+
|
|
1125
|
+
- ``var`` -- string
|
|
1126
|
+
|
|
1127
|
+
OUTPUT: string
|
|
1128
|
+
|
|
1129
|
+
EXAMPLES::
|
|
1130
|
+
|
|
1131
|
+
sage: r.set('a', 2)
|
|
1132
|
+
sage: r.get('a')
|
|
1133
|
+
'[1] 2'
|
|
1134
|
+
"""
|
|
1135
|
+
return self.eval('%s' % var)
|
|
1136
|
+
|
|
1137
|
+
def na(self):
|
|
1138
|
+
"""
|
|
1139
|
+
Return the NA in R.
|
|
1140
|
+
|
|
1141
|
+
OUTPUT: RElement; an element of R
|
|
1142
|
+
|
|
1143
|
+
EXAMPLES::
|
|
1144
|
+
|
|
1145
|
+
sage: r.na()
|
|
1146
|
+
[1] NA
|
|
1147
|
+
"""
|
|
1148
|
+
return self('NA')
|
|
1149
|
+
|
|
1150
|
+
def completions(self, s):
|
|
1151
|
+
"""
|
|
1152
|
+
Return all commands names that complete the command starting with the
|
|
1153
|
+
string s. This is like typing s[Ctrl-T] in the R interpreter.
|
|
1154
|
+
|
|
1155
|
+
INPUT:
|
|
1156
|
+
|
|
1157
|
+
- ``s`` -- string
|
|
1158
|
+
|
|
1159
|
+
OUTPUT: list of strings
|
|
1160
|
+
|
|
1161
|
+
EXAMPLES::
|
|
1162
|
+
|
|
1163
|
+
sage: dummy = r._tab_completion(use_disk_cache=False) # clean doctest
|
|
1164
|
+
sage: 'testInheritedMethods' in r.completions('tes')
|
|
1165
|
+
True
|
|
1166
|
+
"""
|
|
1167
|
+
return [name for name in self._tab_completion() if name[:len(s)] == s]
|
|
1168
|
+
|
|
1169
|
+
def _commands(self):
|
|
1170
|
+
"""
|
|
1171
|
+
Return list of all commands defined in R.
|
|
1172
|
+
|
|
1173
|
+
OUTPUT: list; a sorted list of strings
|
|
1174
|
+
|
|
1175
|
+
EXAMPLES::
|
|
1176
|
+
|
|
1177
|
+
sage: l = r._commands()
|
|
1178
|
+
sage: 'AIC' in l
|
|
1179
|
+
True
|
|
1180
|
+
sage: len(l) > 200
|
|
1181
|
+
True
|
|
1182
|
+
"""
|
|
1183
|
+
v = RBaseCommands
|
|
1184
|
+
|
|
1185
|
+
ll = self('search()')._sage_() # loaded libs
|
|
1186
|
+
|
|
1187
|
+
for lib in ll:
|
|
1188
|
+
if lib in RFilteredPackages:
|
|
1189
|
+
continue
|
|
1190
|
+
|
|
1191
|
+
if lib.find("package:") != 0:
|
|
1192
|
+
continue # only packages
|
|
1193
|
+
|
|
1194
|
+
raw = self('objects("%s")' % lib)._sage_()
|
|
1195
|
+
|
|
1196
|
+
# TODO are there others? many of them are shortcuts or
|
|
1197
|
+
# should be done on another level, like selections in lists
|
|
1198
|
+
# instead of calling obj.[[( fun-args) or
|
|
1199
|
+
# other crazy stuff like that
|
|
1200
|
+
|
|
1201
|
+
# TODO further filtering, check if strings are now
|
|
1202
|
+
# really functions, in R: exists(s, mode = "function"))
|
|
1203
|
+
# (apply to vector with sapply(vec,func))
|
|
1204
|
+
|
|
1205
|
+
# filter only python compatible identifiers
|
|
1206
|
+
valid = re.compile('[^a-zA-Z0-9_]+')
|
|
1207
|
+
raw = [x for x in raw if valid.search(x) is None]
|
|
1208
|
+
v += raw
|
|
1209
|
+
|
|
1210
|
+
v.sort()
|
|
1211
|
+
return v
|
|
1212
|
+
|
|
1213
|
+
def _tab_completion(self, verbose=True, use_disk_cache=True):
|
|
1214
|
+
"""
|
|
1215
|
+
Return list of all R functions.
|
|
1216
|
+
|
|
1217
|
+
INPUT:
|
|
1218
|
+
|
|
1219
|
+
- ``verbose`` -- boolean (default: ``True``); if ``True``, display
|
|
1220
|
+
debugging information
|
|
1221
|
+
- ``use_disk_cache`` -- boolean (default: ``True``); if ``True``, use
|
|
1222
|
+
the disk cache of tab completions to save time
|
|
1223
|
+
|
|
1224
|
+
OUTPUT: list of string
|
|
1225
|
+
|
|
1226
|
+
EXAMPLES::
|
|
1227
|
+
|
|
1228
|
+
sage: t = r._tab_completion(verbose=False)
|
|
1229
|
+
sage: len(t) > 200
|
|
1230
|
+
True
|
|
1231
|
+
"""
|
|
1232
|
+
try:
|
|
1233
|
+
return self.__tab_completion
|
|
1234
|
+
except AttributeError:
|
|
1235
|
+
import sage.misc.persist
|
|
1236
|
+
if use_disk_cache:
|
|
1237
|
+
try:
|
|
1238
|
+
self.__tab_completion = sage.misc.persist.load(COMMANDS_CACHE)
|
|
1239
|
+
return self.__tab_completion
|
|
1240
|
+
except OSError:
|
|
1241
|
+
pass
|
|
1242
|
+
if verbose and use_disk_cache:
|
|
1243
|
+
print("\nBuilding R command completion list (this takes")
|
|
1244
|
+
print("a few seconds only the first time you do it).")
|
|
1245
|
+
print("To force rebuild later, delete %s." % COMMANDS_CACHE)
|
|
1246
|
+
v = self._commands()
|
|
1247
|
+
self.__tab_completion = v
|
|
1248
|
+
if len(v) > 200 and use_disk_cache:
|
|
1249
|
+
sage.misc.persist.save(v, COMMANDS_CACHE)
|
|
1250
|
+
return v
|
|
1251
|
+
|
|
1252
|
+
def plot(self, *args, **kwds):
|
|
1253
|
+
"""
|
|
1254
|
+
The R plot function. Type r.help('plot') for much more extensive
|
|
1255
|
+
documentation about this function. See also below for a brief
|
|
1256
|
+
introduction to more plotting with R.
|
|
1257
|
+
|
|
1258
|
+
If one simply wants to view an R graphic, using this function is
|
|
1259
|
+
is sufficient (because it calls dev.off() to turn off the device).
|
|
1260
|
+
|
|
1261
|
+
However, if one wants to save the graphic to a specific file, it
|
|
1262
|
+
should be used as in the example below to write the output.
|
|
1263
|
+
|
|
1264
|
+
EXAMPLES:
|
|
1265
|
+
|
|
1266
|
+
This example saves a plot to the standard R output, usually a
|
|
1267
|
+
filename like ``Rplot001.png`` - from the command line, in the
|
|
1268
|
+
current directory, and in the cell directory in the
|
|
1269
|
+
notebook. We use a temporary directory in this example while
|
|
1270
|
+
doctesting this example, but you should use something
|
|
1271
|
+
persistent in your own code::
|
|
1272
|
+
|
|
1273
|
+
sage: from tempfile import TemporaryDirectory
|
|
1274
|
+
sage: with TemporaryDirectory() as d: # optional - rgraphics
|
|
1275
|
+
....: _ = r.setwd(d)
|
|
1276
|
+
....: r.plot("1:10")
|
|
1277
|
+
null device
|
|
1278
|
+
1
|
|
1279
|
+
|
|
1280
|
+
To save to a specific file name, one should use :meth:`png` to set
|
|
1281
|
+
the output device to that file. If this is done in the notebook, it
|
|
1282
|
+
must be done in the same cell as the plot itself::
|
|
1283
|
+
|
|
1284
|
+
sage: filename = tmp_filename() + '.png'
|
|
1285
|
+
sage: r.png(filename='"%s"'%filename) # optional - rgraphics
|
|
1286
|
+
NULL
|
|
1287
|
+
sage: x = r([1,2,3])
|
|
1288
|
+
sage: y = r([4,5,6])
|
|
1289
|
+
sage: r.plot(x,y) # optional - rgraphics
|
|
1290
|
+
null device
|
|
1291
|
+
1
|
|
1292
|
+
sage: import os; os.unlink(filename) # optional - rgraphics
|
|
1293
|
+
|
|
1294
|
+
Please note that for more extensive use of R's plotting
|
|
1295
|
+
capabilities (such as the lattices package), it is advisable
|
|
1296
|
+
to either use an interactive plotting device or to use the
|
|
1297
|
+
notebook. The following examples are not tested, because they
|
|
1298
|
+
differ depending on operating system::
|
|
1299
|
+
|
|
1300
|
+
sage: # not tested
|
|
1301
|
+
sage: r.X11()
|
|
1302
|
+
sage: r.quartz()
|
|
1303
|
+
sage: r.hist("rnorm(100)")
|
|
1304
|
+
sage: r.library("lattice")
|
|
1305
|
+
sage: r.histogram(x = '~ wt | cyl', data='mtcars')
|
|
1306
|
+
sage: r.dev_off()
|
|
1307
|
+
|
|
1308
|
+
In the notebook, one can use r.png() to open the device, but
|
|
1309
|
+
would need to use the following since R lattice graphics do
|
|
1310
|
+
not automatically print away from the command line::
|
|
1311
|
+
|
|
1312
|
+
sage: filename = tmp_filename() + '.png' # not needed in notebook, used for doctesting
|
|
1313
|
+
sage: r.png(filename='"%s"'%filename) # optional - rgraphics
|
|
1314
|
+
NULL
|
|
1315
|
+
sage: r.library("lattice")
|
|
1316
|
+
sage: r("print(histogram(~wt | cyl, data=mtcars))") # optional - rgraphics
|
|
1317
|
+
sage: import os; os.unlink(filename) # optional - rgraphics
|
|
1318
|
+
"""
|
|
1319
|
+
# We have to define this to override the plot function defined in the
|
|
1320
|
+
# superclass.
|
|
1321
|
+
RFunction(self, 'plot')(*args, **kwds)
|
|
1322
|
+
return RFunction(self, 'dev.off')()
|
|
1323
|
+
|
|
1324
|
+
def eval(self, code, *args, **kwds):
|
|
1325
|
+
"""
|
|
1326
|
+
Evaluates a command inside the R interpreter and returns the output
|
|
1327
|
+
as a string.
|
|
1328
|
+
|
|
1329
|
+
EXAMPLES::
|
|
1330
|
+
|
|
1331
|
+
sage: r.eval('1+1')
|
|
1332
|
+
'[1] 2'
|
|
1333
|
+
"""
|
|
1334
|
+
self._lazy_init()
|
|
1335
|
+
return str(robjects.r(code)).rstrip()
|
|
1336
|
+
|
|
1337
|
+
def _r_to_sage_name(self, s):
|
|
1338
|
+
"""
|
|
1339
|
+
Return a Sage/Python identifier from an R one. This involves
|
|
1340
|
+
replacing periods with underscores, <- with __, and prepending
|
|
1341
|
+
_ in front of Python keywords.
|
|
1342
|
+
|
|
1343
|
+
INPUT:
|
|
1344
|
+
|
|
1345
|
+
- ``s`` -- string
|
|
1346
|
+
|
|
1347
|
+
OUTPUT: string
|
|
1348
|
+
|
|
1349
|
+
EXAMPLES::
|
|
1350
|
+
|
|
1351
|
+
sage: f = r._r_to_sage_name
|
|
1352
|
+
sage: f('t.test')
|
|
1353
|
+
't_test'
|
|
1354
|
+
sage: f('attr<-')
|
|
1355
|
+
'attr__'
|
|
1356
|
+
sage: f('parent.env<-')
|
|
1357
|
+
'parent_env__'
|
|
1358
|
+
sage: f('class')
|
|
1359
|
+
'class_'
|
|
1360
|
+
"""
|
|
1361
|
+
from keyword import iskeyword
|
|
1362
|
+
s = s.replace('.', '_')
|
|
1363
|
+
s = s.replace('<-', '__')
|
|
1364
|
+
if iskeyword(s):
|
|
1365
|
+
s += '_'
|
|
1366
|
+
return s
|
|
1367
|
+
|
|
1368
|
+
def _sage_to_r_name(self, s):
|
|
1369
|
+
r"""
|
|
1370
|
+
The reverse of :meth:`_r_to_sage_name`. See the docs for that method.
|
|
1371
|
+
|
|
1372
|
+
EXAMPLES::
|
|
1373
|
+
|
|
1374
|
+
sage: f = r._sage_to_r_name
|
|
1375
|
+
sage: f('t_test')
|
|
1376
|
+
't.test'
|
|
1377
|
+
sage: f('attr__')
|
|
1378
|
+
'attr<-'
|
|
1379
|
+
sage: f('parent_env__')
|
|
1380
|
+
'parent.env<-'
|
|
1381
|
+
sage: r._r_to_sage_name(f('parent_env__'))
|
|
1382
|
+
'parent_env__'
|
|
1383
|
+
sage: f('class_')
|
|
1384
|
+
'class'
|
|
1385
|
+
"""
|
|
1386
|
+
if len(s) > 1 and s[-2:] == "__":
|
|
1387
|
+
s = s[:-2] + '<-'
|
|
1388
|
+
if len(s) > 0 and s[-1] == '_':
|
|
1389
|
+
s = s[:-1]
|
|
1390
|
+
s = s.replace('_', '.')
|
|
1391
|
+
return s
|
|
1392
|
+
|
|
1393
|
+
def __getitem__(self, s):
|
|
1394
|
+
"""
|
|
1395
|
+
Return the RFunction with name s.
|
|
1396
|
+
|
|
1397
|
+
INPUT:
|
|
1398
|
+
|
|
1399
|
+
- ``s`` -- string
|
|
1400
|
+
|
|
1401
|
+
OUTPUT: RFunction; the R function that in R has name s
|
|
1402
|
+
|
|
1403
|
+
EXAMPLES::
|
|
1404
|
+
|
|
1405
|
+
sage: r['as.data.frame']
|
|
1406
|
+
as.data.frame
|
|
1407
|
+
sage: r['print']
|
|
1408
|
+
print
|
|
1409
|
+
"""
|
|
1410
|
+
return RFunction(self, s, r_name=True)
|
|
1411
|
+
|
|
1412
|
+
def chdir(self, dir):
|
|
1413
|
+
"""
|
|
1414
|
+
Changes the working directory to ``dir``.
|
|
1415
|
+
|
|
1416
|
+
INPUT:
|
|
1417
|
+
|
|
1418
|
+
- ``dir`` -- the directory to change to
|
|
1419
|
+
|
|
1420
|
+
EXAMPLES::
|
|
1421
|
+
|
|
1422
|
+
sage: import tempfile
|
|
1423
|
+
sage: tmpdir = tempfile.mkdtemp()
|
|
1424
|
+
sage: r.chdir(tmpdir)
|
|
1425
|
+
|
|
1426
|
+
Check that ``tmpdir`` and ``r.getwd()`` refer to the same
|
|
1427
|
+
directory. We need to use ``realpath()`` in case ``$TMPDIR``
|
|
1428
|
+
(by default ``/tmp``) is a symbolic link (see :issue:`10264`).
|
|
1429
|
+
|
|
1430
|
+
::
|
|
1431
|
+
|
|
1432
|
+
sage: os.path.realpath(tmpdir) == sageobj(r.getwd()) # known bug (issue #9970)
|
|
1433
|
+
True
|
|
1434
|
+
"""
|
|
1435
|
+
self.execute('setwd(%r)' % dir)
|
|
1436
|
+
|
|
1437
|
+
|
|
1438
|
+
@instancedoc
|
|
1439
|
+
class RElement(ExtraTabCompletion, InterfaceElement):
|
|
1440
|
+
|
|
1441
|
+
def _tab_completion(self):
|
|
1442
|
+
"""
|
|
1443
|
+
Return a list of all methods of this object.
|
|
1444
|
+
|
|
1445
|
+
.. NOTE::
|
|
1446
|
+
|
|
1447
|
+
Currently returns all R commands.
|
|
1448
|
+
|
|
1449
|
+
EXAMPLES::
|
|
1450
|
+
|
|
1451
|
+
sage: a = r([1,2,3])
|
|
1452
|
+
sage: t = a._tab_completion()
|
|
1453
|
+
sage: len(t) > 200
|
|
1454
|
+
True
|
|
1455
|
+
"""
|
|
1456
|
+
# TODO: rewrite it, just take methods(class=class(self))
|
|
1457
|
+
return self.parent()._tab_completion()
|
|
1458
|
+
|
|
1459
|
+
def tilde(self, x):
|
|
1460
|
+
"""
|
|
1461
|
+
The tilde regression operator in R.
|
|
1462
|
+
|
|
1463
|
+
EXAMPLES::
|
|
1464
|
+
|
|
1465
|
+
sage: x = r([1,2,3,4,5])
|
|
1466
|
+
sage: y = r([3,5,7,9,11])
|
|
1467
|
+
sage: a = r.lm( y.tilde(x) ) # lm( y ~ x )
|
|
1468
|
+
sage: d = a._sage_()
|
|
1469
|
+
sage: d['DATA']['coefficients']['DATA'][1]
|
|
1470
|
+
2
|
|
1471
|
+
"""
|
|
1472
|
+
par = self.parent()
|
|
1473
|
+
rx = par(x)
|
|
1474
|
+
return par.new("%s ~ %s" % (self.name(), rx.name()))
|
|
1475
|
+
|
|
1476
|
+
stat_model = tilde
|
|
1477
|
+
|
|
1478
|
+
def is_string(self):
|
|
1479
|
+
"""
|
|
1480
|
+
Tell whether this element is a string.
|
|
1481
|
+
|
|
1482
|
+
EXAMPLES::
|
|
1483
|
+
|
|
1484
|
+
sage: r('"abc"').is_string()
|
|
1485
|
+
True
|
|
1486
|
+
sage: r([1,2,3]).is_string()
|
|
1487
|
+
False
|
|
1488
|
+
"""
|
|
1489
|
+
return isinstance(self.sage(), str)
|
|
1490
|
+
|
|
1491
|
+
def __len__(self):
|
|
1492
|
+
"""
|
|
1493
|
+
Return the length of this object.
|
|
1494
|
+
|
|
1495
|
+
OUTPUT: integer
|
|
1496
|
+
|
|
1497
|
+
EXAMPLES::
|
|
1498
|
+
|
|
1499
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1500
|
+
sage: len(x)
|
|
1501
|
+
5
|
|
1502
|
+
"""
|
|
1503
|
+
return self.parent()('length(%s)' % self.name()).sage()
|
|
1504
|
+
|
|
1505
|
+
def __getattr__(self, attrname):
|
|
1506
|
+
"""
|
|
1507
|
+
Return attribute of this object, which is an R function with this object
|
|
1508
|
+
as the first input.
|
|
1509
|
+
|
|
1510
|
+
INPUT:
|
|
1511
|
+
|
|
1512
|
+
- ``attrname`` -- string
|
|
1513
|
+
|
|
1514
|
+
OUTPUT: RFunctionElement
|
|
1515
|
+
|
|
1516
|
+
EXAMPLES::
|
|
1517
|
+
|
|
1518
|
+
sage: x = r([1,2,3])
|
|
1519
|
+
sage: length = x.length
|
|
1520
|
+
sage: type(length)
|
|
1521
|
+
<class 'sage.interfaces.r.RFunctionElement'>
|
|
1522
|
+
sage: length()
|
|
1523
|
+
[1] 3
|
|
1524
|
+
"""
|
|
1525
|
+
try:
|
|
1526
|
+
# First try to get a regular python attribute. This makes it
|
|
1527
|
+
# possible to still use attributes like _r_to_sage_converter
|
|
1528
|
+
# internally.
|
|
1529
|
+
self.__getattribute__(attrname)
|
|
1530
|
+
except AttributeError:
|
|
1531
|
+
self._check_valid()
|
|
1532
|
+
if attrname[:1] == "_":
|
|
1533
|
+
raise AttributeError("Attribute {} is not allowed to start with an underscore.".format(attrname))
|
|
1534
|
+
return RFunctionElement(self, attrname)
|
|
1535
|
+
|
|
1536
|
+
def __getitem__(self, n):
|
|
1537
|
+
"""
|
|
1538
|
+
Return element(s) of ``self``.
|
|
1539
|
+
|
|
1540
|
+
INPUT:
|
|
1541
|
+
|
|
1542
|
+
- ``n`` -- integer, a tuple, a string that makes sense to R, or an
|
|
1543
|
+
RElement
|
|
1544
|
+
|
|
1545
|
+
OUTPUT: RElement
|
|
1546
|
+
|
|
1547
|
+
EXAMPLES::
|
|
1548
|
+
|
|
1549
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1550
|
+
sage: x[0]
|
|
1551
|
+
numeric(0)
|
|
1552
|
+
sage: x[1]
|
|
1553
|
+
[1] 10.4
|
|
1554
|
+
sage: x[-1]
|
|
1555
|
+
[1] 5.6 3.1 6.4 21.7
|
|
1556
|
+
sage: x[-2]
|
|
1557
|
+
[1] 10.4 3.1 6.4 21.7
|
|
1558
|
+
sage: x[-3]
|
|
1559
|
+
[1] 10.4 5.6 6.4 21.7
|
|
1560
|
+
sage: x['c(2,3)']
|
|
1561
|
+
[1] 5.6 3.1
|
|
1562
|
+
sage: key = r.c(2,3)
|
|
1563
|
+
sage: x[key]
|
|
1564
|
+
[1] 5.6 3.1
|
|
1565
|
+
sage: m = r.array('1:3',r.c(2,4,2))
|
|
1566
|
+
sage: m
|
|
1567
|
+
, , 1
|
|
1568
|
+
[,1] [,2] [,3] [,4]
|
|
1569
|
+
[1,] 1 3 2 1
|
|
1570
|
+
[2,] 2 1 3 2
|
|
1571
|
+
, , 2
|
|
1572
|
+
[,1] [,2] [,3] [,4]
|
|
1573
|
+
[1,] 3 2 1 3
|
|
1574
|
+
[2,] 1 3 2 1
|
|
1575
|
+
sage: m[1,2,2]
|
|
1576
|
+
[1] 2
|
|
1577
|
+
sage: m[1,r.c(1,2),1]
|
|
1578
|
+
[1] 1 3
|
|
1579
|
+
"""
|
|
1580
|
+
P = self._check_valid()
|
|
1581
|
+
if isinstance(n, str):
|
|
1582
|
+
n = n.replace('self', self._name)
|
|
1583
|
+
return P.new('%s[%s]' % (self._name, n))
|
|
1584
|
+
elif parent(n) is P: # the key is RElement itself
|
|
1585
|
+
return P.new('%s[%s]' % (self._name, n.name()))
|
|
1586
|
+
elif not isinstance(n, tuple):
|
|
1587
|
+
return P.new('%s[%s]' % (self._name, n))
|
|
1588
|
+
else:
|
|
1589
|
+
L = []
|
|
1590
|
+
for i in range(len(n)):
|
|
1591
|
+
if parent(n[i]) is P:
|
|
1592
|
+
L.append(n[i].name())
|
|
1593
|
+
else:
|
|
1594
|
+
L.append(str(n[i]))
|
|
1595
|
+
return P.new('%s[%s]' % (self._name, ','.join(L)))
|
|
1596
|
+
|
|
1597
|
+
def __bool__(self):
|
|
1598
|
+
"""
|
|
1599
|
+
Implement ``bool(self)``.
|
|
1600
|
+
|
|
1601
|
+
.. NOTE::
|
|
1602
|
+
|
|
1603
|
+
bool(self) will only return ``True`` if ``self == 0`` contains a
|
|
1604
|
+
FALSE in its representation.
|
|
1605
|
+
|
|
1606
|
+
EXAMPLES::
|
|
1607
|
+
|
|
1608
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1609
|
+
sage: bool(x)
|
|
1610
|
+
True
|
|
1611
|
+
sage: y = r([0,0,0,0])
|
|
1612
|
+
sage: bool(y)
|
|
1613
|
+
False
|
|
1614
|
+
sage: bool(r(0))
|
|
1615
|
+
False
|
|
1616
|
+
sage: bool(r(1))
|
|
1617
|
+
True
|
|
1618
|
+
"""
|
|
1619
|
+
return "FALSE" in repr(self == 0)
|
|
1620
|
+
|
|
1621
|
+
def _comparison(self, other, symbol):
|
|
1622
|
+
"""
|
|
1623
|
+
Used to implement comparison of two objects.
|
|
1624
|
+
|
|
1625
|
+
INPUT:
|
|
1626
|
+
|
|
1627
|
+
- ``other`` -- RElement
|
|
1628
|
+
- ``symbol`` -- string
|
|
1629
|
+
|
|
1630
|
+
OUTPUT: RElement; output is an R element (not a bool!)
|
|
1631
|
+
|
|
1632
|
+
TESTS::
|
|
1633
|
+
|
|
1634
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1635
|
+
sage: x._comparison(10.4, "==")
|
|
1636
|
+
[1] TRUE FALSE FALSE FALSE FALSE
|
|
1637
|
+
"""
|
|
1638
|
+
P = self.parent()
|
|
1639
|
+
other = P(other)
|
|
1640
|
+
return P('%s %s %s' % (self.name(), symbol, other.name()))
|
|
1641
|
+
|
|
1642
|
+
def __eq__(self, other):
|
|
1643
|
+
"""
|
|
1644
|
+
Equality testing term by term.
|
|
1645
|
+
|
|
1646
|
+
INPUT:
|
|
1647
|
+
|
|
1648
|
+
- ``other`` -- RElement
|
|
1649
|
+
|
|
1650
|
+
OUTPUT: RElement; an R element (not a bool!)
|
|
1651
|
+
|
|
1652
|
+
EXAMPLES:
|
|
1653
|
+
|
|
1654
|
+
Notice that comparison is term by term and returns an R element. ::
|
|
1655
|
+
|
|
1656
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1657
|
+
sage: x == 10.4
|
|
1658
|
+
[1] TRUE FALSE FALSE FALSE FALSE
|
|
1659
|
+
"""
|
|
1660
|
+
return self._comparison(other, "==")
|
|
1661
|
+
|
|
1662
|
+
def __lt__(self, other):
|
|
1663
|
+
"""
|
|
1664
|
+
Less than testing term by term.
|
|
1665
|
+
|
|
1666
|
+
INPUT:
|
|
1667
|
+
|
|
1668
|
+
- ``other`` -- RElement
|
|
1669
|
+
|
|
1670
|
+
OUTPUT: RElement; an R element (not a bool!)
|
|
1671
|
+
|
|
1672
|
+
EXAMPLES:
|
|
1673
|
+
|
|
1674
|
+
Notice that comparison is term by term and returns an R element. ::
|
|
1675
|
+
|
|
1676
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1677
|
+
sage: x < 7
|
|
1678
|
+
[1] FALSE TRUE TRUE TRUE FALSE
|
|
1679
|
+
"""
|
|
1680
|
+
return self._comparison(other, "<")
|
|
1681
|
+
|
|
1682
|
+
def __gt__(self, other):
|
|
1683
|
+
"""
|
|
1684
|
+
Greater than testing term by term.
|
|
1685
|
+
|
|
1686
|
+
INPUT:
|
|
1687
|
+
|
|
1688
|
+
- ``other`` -- RElement
|
|
1689
|
+
|
|
1690
|
+
OUTPUT: RElement; an R element (not a bool!)
|
|
1691
|
+
|
|
1692
|
+
EXAMPLES:
|
|
1693
|
+
|
|
1694
|
+
Notice that comparison is term by term and returns an R element. ::
|
|
1695
|
+
|
|
1696
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1697
|
+
sage: x > 8
|
|
1698
|
+
[1] TRUE FALSE FALSE FALSE TRUE
|
|
1699
|
+
"""
|
|
1700
|
+
return self._comparison(other, ">")
|
|
1701
|
+
|
|
1702
|
+
def __le__(self, other):
|
|
1703
|
+
"""
|
|
1704
|
+
Less than or equal testing term by term.
|
|
1705
|
+
|
|
1706
|
+
INPUT:
|
|
1707
|
+
|
|
1708
|
+
- ``other`` -- RElement
|
|
1709
|
+
|
|
1710
|
+
OUTPUT: RElement; an R element (not a bool!)
|
|
1711
|
+
|
|
1712
|
+
EXAMPLES::
|
|
1713
|
+
|
|
1714
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1715
|
+
sage: x <= 10.4
|
|
1716
|
+
[1] TRUE TRUE TRUE TRUE FALSE
|
|
1717
|
+
"""
|
|
1718
|
+
return self._comparison(other, "<=")
|
|
1719
|
+
|
|
1720
|
+
def __ge__(self, other):
|
|
1721
|
+
"""
|
|
1722
|
+
Greater than or equal testing term by term.
|
|
1723
|
+
|
|
1724
|
+
INPUT:
|
|
1725
|
+
|
|
1726
|
+
- ``other`` -- RElement
|
|
1727
|
+
|
|
1728
|
+
OUTPUT: RElement; an R element (not a bool!)
|
|
1729
|
+
|
|
1730
|
+
EXAMPLES::
|
|
1731
|
+
|
|
1732
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1733
|
+
sage: x >= 10.4
|
|
1734
|
+
[1] TRUE FALSE FALSE FALSE TRUE
|
|
1735
|
+
"""
|
|
1736
|
+
return self._comparison(other, ">=")
|
|
1737
|
+
|
|
1738
|
+
def __ne__(self, other):
|
|
1739
|
+
"""
|
|
1740
|
+
Not equal testing term by term.
|
|
1741
|
+
|
|
1742
|
+
INPUT:
|
|
1743
|
+
|
|
1744
|
+
- ``other`` -- RElement
|
|
1745
|
+
|
|
1746
|
+
OUTPUT: RElement; an R element (not a bool!)
|
|
1747
|
+
|
|
1748
|
+
EXAMPLES::
|
|
1749
|
+
|
|
1750
|
+
sage: x = r([10.4,5.6,3.1,6.4,21.7])
|
|
1751
|
+
sage: x != 10.4
|
|
1752
|
+
[1] FALSE TRUE TRUE TRUE TRUE
|
|
1753
|
+
"""
|
|
1754
|
+
return self._comparison(other, "!=")
|
|
1755
|
+
|
|
1756
|
+
def dot_product(self, other):
|
|
1757
|
+
"""
|
|
1758
|
+
Implement the notation ``self . other``.
|
|
1759
|
+
|
|
1760
|
+
INPUT:
|
|
1761
|
+
|
|
1762
|
+
- ``self``, ``other`` -- R elements
|
|
1763
|
+
|
|
1764
|
+
OUTPUT: R element
|
|
1765
|
+
|
|
1766
|
+
EXAMPLES::
|
|
1767
|
+
|
|
1768
|
+
sage: c = r.c(1,2,3,4)
|
|
1769
|
+
sage: c.dot_product(c.t())
|
|
1770
|
+
[,1] [,2] [,3] [,4]
|
|
1771
|
+
[1,] 1 2 3 4
|
|
1772
|
+
[2,] 2 4 6 8
|
|
1773
|
+
[3,] 3 6 9 12
|
|
1774
|
+
[4,] 4 8 12 16
|
|
1775
|
+
|
|
1776
|
+
sage: v = r([3,-1,8])
|
|
1777
|
+
sage: v.dot_product(v)
|
|
1778
|
+
[,1]
|
|
1779
|
+
[1,] 74
|
|
1780
|
+
"""
|
|
1781
|
+
P = self._check_valid()
|
|
1782
|
+
Q = P(other)
|
|
1783
|
+
# the R operator is %*% for matrix multiplication
|
|
1784
|
+
return P('%s %%*%% %s' % (self.name(), Q.name()))
|
|
1785
|
+
|
|
1786
|
+
def _sage_(self):
|
|
1787
|
+
r"""
|
|
1788
|
+
Return Sage representation of the R object.
|
|
1789
|
+
|
|
1790
|
+
R objects are basic C structures, of different kind, that can
|
|
1791
|
+
be stacked together. This is similar to Python lists with
|
|
1792
|
+
variable objects, including lists of lists. If R lists have
|
|
1793
|
+
names, they are translated to a Python dictionary, with anonymous
|
|
1794
|
+
list entries called ``#{number}``.
|
|
1795
|
+
|
|
1796
|
+
OUTPUT: object; Python object
|
|
1797
|
+
|
|
1798
|
+
EXAMPLES::
|
|
1799
|
+
|
|
1800
|
+
sage: rs = r.summary(r.c(1,4,3,4,3,2,5,1))
|
|
1801
|
+
sage: d = rs._sage_()
|
|
1802
|
+
sage: sorted(d.items())
|
|
1803
|
+
[('DATA', [1, 1.75, 3, 2.875, 4, 5]),
|
|
1804
|
+
('_Names', ['Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.']),
|
|
1805
|
+
('_r_class', ['summaryDefault', 'table'])]
|
|
1806
|
+
"""
|
|
1807
|
+
self._check_valid()
|
|
1808
|
+
P = self.parent()
|
|
1809
|
+
|
|
1810
|
+
with localconverter(P._r_to_sage_converter) as cv:
|
|
1811
|
+
return robjects.r(self.name())
|
|
1812
|
+
|
|
1813
|
+
def _latex_(self):
|
|
1814
|
+
r"""
|
|
1815
|
+
Return LaTeX representation of this R object.
|
|
1816
|
+
|
|
1817
|
+
This calls the ``latex`` command in R.
|
|
1818
|
+
|
|
1819
|
+
OUTPUT: a latex expression (basically a string)
|
|
1820
|
+
|
|
1821
|
+
EXAMPLES::
|
|
1822
|
+
|
|
1823
|
+
sage: latex(r(2)) # optional - Hmisc (R package)
|
|
1824
|
+
2
|
|
1825
|
+
"""
|
|
1826
|
+
from sage.misc.latex import LatexExpr
|
|
1827
|
+
self._check_valid()
|
|
1828
|
+
P = self.parent()
|
|
1829
|
+
# latex is in Hmisc, this is currently not part of Sage's R!!!
|
|
1830
|
+
try:
|
|
1831
|
+
P.library('Hmisc')
|
|
1832
|
+
except ImportError:
|
|
1833
|
+
raise RuntimeError("The R package 'Hmisc' is required for R to LaTeX conversion, but it is not available.")
|
|
1834
|
+
return LatexExpr(P.eval('latex(%s, file="");' % self.name()))
|
|
1835
|
+
|
|
1836
|
+
|
|
1837
|
+
@instancedoc
|
|
1838
|
+
class RFunctionElement(InterfaceFunctionElement):
|
|
1839
|
+
def __reduce__(self):
|
|
1840
|
+
"""
|
|
1841
|
+
EXAMPLES::
|
|
1842
|
+
|
|
1843
|
+
sage: a = r([1,2,3])
|
|
1844
|
+
sage: a.mean
|
|
1845
|
+
mean
|
|
1846
|
+
sage: dumps(a.mean)
|
|
1847
|
+
Traceback (most recent call last):
|
|
1848
|
+
...
|
|
1849
|
+
NotImplementedError: pickling of R element methods is not yet supported
|
|
1850
|
+
"""
|
|
1851
|
+
raise NotImplementedError("pickling of R element methods is not yet supported")
|
|
1852
|
+
|
|
1853
|
+
def _instancedoc_(self):
|
|
1854
|
+
"""
|
|
1855
|
+
Return the help for ``self`` as a string.
|
|
1856
|
+
|
|
1857
|
+
EXAMPLES::
|
|
1858
|
+
|
|
1859
|
+
sage: a = r([1,2,3])
|
|
1860
|
+
sage: length = a.length
|
|
1861
|
+
sage: print(length.__doc__)
|
|
1862
|
+
title
|
|
1863
|
+
-----
|
|
1864
|
+
<BLANKLINE>
|
|
1865
|
+
Length of an Object
|
|
1866
|
+
<BLANKLINE>
|
|
1867
|
+
name
|
|
1868
|
+
----
|
|
1869
|
+
<BLANKLINE>
|
|
1870
|
+
length
|
|
1871
|
+
...
|
|
1872
|
+
"""
|
|
1873
|
+
M = self._obj.parent()
|
|
1874
|
+
return M.help(self._name)
|
|
1875
|
+
|
|
1876
|
+
def _sage_src_(self):
|
|
1877
|
+
"""
|
|
1878
|
+
Return the source code of ``self``.
|
|
1879
|
+
|
|
1880
|
+
EXAMPLES::
|
|
1881
|
+
|
|
1882
|
+
sage: a = r([1,2,3])
|
|
1883
|
+
sage: length = a.length
|
|
1884
|
+
sage: print(length._sage_src_())
|
|
1885
|
+
function (x) .Primitive("length")
|
|
1886
|
+
"""
|
|
1887
|
+
M = self._obj.parent()
|
|
1888
|
+
return M.source(self._name)
|
|
1889
|
+
|
|
1890
|
+
def __call__(self, *args, **kwds):
|
|
1891
|
+
"""
|
|
1892
|
+
EXAMPLES::
|
|
1893
|
+
|
|
1894
|
+
sage: a = r([1,2,3])
|
|
1895
|
+
sage: length = a.length
|
|
1896
|
+
sage: length()
|
|
1897
|
+
[1] 3
|
|
1898
|
+
"""
|
|
1899
|
+
return self._obj.parent().function_call(self._name, args=[self._obj] + list(args), kwds=kwds)
|
|
1900
|
+
|
|
1901
|
+
|
|
1902
|
+
@instancedoc
|
|
1903
|
+
class RFunction(InterfaceFunction):
|
|
1904
|
+
def __init__(self, parent, name, r_name=None):
|
|
1905
|
+
"""
|
|
1906
|
+
A Function in the R interface.
|
|
1907
|
+
|
|
1908
|
+
INPUT:
|
|
1909
|
+
|
|
1910
|
+
- ``parent`` -- the R interface
|
|
1911
|
+
- ``name`` -- the name of the function for Python
|
|
1912
|
+
- ``r_name`` -- the name of the function in R itself (which can have dots in it)
|
|
1913
|
+
|
|
1914
|
+
EXAMPLES::
|
|
1915
|
+
|
|
1916
|
+
sage: length = r.length
|
|
1917
|
+
sage: type(length)
|
|
1918
|
+
<class 'sage.interfaces.r.RFunction'>
|
|
1919
|
+
sage: loads(dumps(length))
|
|
1920
|
+
length
|
|
1921
|
+
"""
|
|
1922
|
+
self._parent = parent
|
|
1923
|
+
if r_name:
|
|
1924
|
+
self._name = name
|
|
1925
|
+
else:
|
|
1926
|
+
self._name = parent._sage_to_r_name(name)
|
|
1927
|
+
|
|
1928
|
+
def __eq__(self, other):
|
|
1929
|
+
"""
|
|
1930
|
+
EXAMPLES::
|
|
1931
|
+
|
|
1932
|
+
sage: r.mean == loads(dumps(r.mean))
|
|
1933
|
+
True
|
|
1934
|
+
sage: r.mean == r.lr
|
|
1935
|
+
False
|
|
1936
|
+
"""
|
|
1937
|
+
return (isinstance(other, RFunction) and
|
|
1938
|
+
self._name == other._name)
|
|
1939
|
+
|
|
1940
|
+
def __ne__(self, other):
|
|
1941
|
+
"""
|
|
1942
|
+
EXAMPLES::
|
|
1943
|
+
|
|
1944
|
+
sage: r.mean != loads(dumps(r.mean))
|
|
1945
|
+
False
|
|
1946
|
+
sage: r.mean != r.lr
|
|
1947
|
+
True
|
|
1948
|
+
"""
|
|
1949
|
+
return not (self == other)
|
|
1950
|
+
|
|
1951
|
+
def _instancedoc_(self):
|
|
1952
|
+
"""
|
|
1953
|
+
Return the help for ``self``.
|
|
1954
|
+
|
|
1955
|
+
EXAMPLES::
|
|
1956
|
+
|
|
1957
|
+
sage: length = r.length
|
|
1958
|
+
sage: print(length.__doc__)
|
|
1959
|
+
title
|
|
1960
|
+
-----
|
|
1961
|
+
<BLANKLINE>
|
|
1962
|
+
Length of an Object
|
|
1963
|
+
<BLANKLINE>
|
|
1964
|
+
name
|
|
1965
|
+
----
|
|
1966
|
+
<BLANKLINE>
|
|
1967
|
+
length
|
|
1968
|
+
...
|
|
1969
|
+
"""
|
|
1970
|
+
M = self._parent
|
|
1971
|
+
return M.help(self._name)
|
|
1972
|
+
|
|
1973
|
+
def _sage_src_(self):
|
|
1974
|
+
"""
|
|
1975
|
+
Return the source of ``self``.
|
|
1976
|
+
|
|
1977
|
+
EXAMPLES::
|
|
1978
|
+
|
|
1979
|
+
sage: length = r.length
|
|
1980
|
+
sage: print(length._sage_src_())
|
|
1981
|
+
function (x) .Primitive("length")
|
|
1982
|
+
"""
|
|
1983
|
+
M = self._parent
|
|
1984
|
+
return M.source(self._name)
|
|
1985
|
+
|
|
1986
|
+
def __call__(self, *args, **kwds):
|
|
1987
|
+
"""
|
|
1988
|
+
EXAMPLES::
|
|
1989
|
+
|
|
1990
|
+
sage: length = r.length
|
|
1991
|
+
sage: length([1,2,3])
|
|
1992
|
+
[1] 3
|
|
1993
|
+
"""
|
|
1994
|
+
return self._parent.function_call(self._name, args=list(args), kwds=kwds)
|
|
1995
|
+
|
|
1996
|
+
|
|
1997
|
+
def is_RElement(x):
|
|
1998
|
+
"""
|
|
1999
|
+
Return ``True`` if x is an element in an R interface.
|
|
2000
|
+
|
|
2001
|
+
INPUT:
|
|
2002
|
+
|
|
2003
|
+
- ``x`` -- object
|
|
2004
|
+
|
|
2005
|
+
OUTPUT: boolean
|
|
2006
|
+
|
|
2007
|
+
EXAMPLES::
|
|
2008
|
+
|
|
2009
|
+
sage: from sage.interfaces.r import is_RElement
|
|
2010
|
+
sage: is_RElement(2)
|
|
2011
|
+
doctest:...: DeprecationWarning: the function is_RElement is deprecated; use isinstance(x, sage.interfaces.abc.RElement) instead
|
|
2012
|
+
See https://github.com/sagemath/sage/issues/34804 for details.
|
|
2013
|
+
False
|
|
2014
|
+
sage: is_RElement(r(2))
|
|
2015
|
+
True
|
|
2016
|
+
"""
|
|
2017
|
+
from sage.misc.superseded import deprecation
|
|
2018
|
+
deprecation(34804, "the function is_RElement is deprecated; use isinstance(x, sage.interfaces.abc.RElement) instead")
|
|
2019
|
+
|
|
2020
|
+
return isinstance(x, RElement)
|
|
2021
|
+
|
|
2022
|
+
|
|
2023
|
+
# An instance of R
|
|
2024
|
+
r = R()
|
|
2025
|
+
|
|
2026
|
+
|
|
2027
|
+
def reduce_load_R():
|
|
2028
|
+
"""
|
|
2029
|
+
Used for reconstructing a copy of the R interpreter from a pickle.
|
|
2030
|
+
|
|
2031
|
+
EXAMPLES::
|
|
2032
|
+
|
|
2033
|
+
sage: from sage.interfaces.r import reduce_load_R
|
|
2034
|
+
sage: reduce_load_R()
|
|
2035
|
+
R Interpreter
|
|
2036
|
+
"""
|
|
2037
|
+
return r
|
|
2038
|
+
|
|
2039
|
+
|
|
2040
|
+
def r_console():
|
|
2041
|
+
"""
|
|
2042
|
+
Spawn a new R command-line session.
|
|
2043
|
+
|
|
2044
|
+
EXAMPLES::
|
|
2045
|
+
|
|
2046
|
+
sage: r.console() # not tested
|
|
2047
|
+
R version 2.6.1 (2007-11-26)
|
|
2048
|
+
Copyright (C) 2007 The R Foundation for Statistical Computing
|
|
2049
|
+
ISBN 3-900051-07-0
|
|
2050
|
+
...
|
|
2051
|
+
"""
|
|
2052
|
+
from sage.repl.rich_output.display_manager import get_display_manager
|
|
2053
|
+
if not get_display_manager().is_in_terminal():
|
|
2054
|
+
raise RuntimeError('Can use the console only in the terminal. Try %%r magics instead.')
|
|
2055
|
+
# This will only spawn local processes
|
|
2056
|
+
os.system('R --vanilla')
|
|
2057
|
+
|
|
2058
|
+
|
|
2059
|
+
def r_version():
|
|
2060
|
+
"""
|
|
2061
|
+
Return the R version.
|
|
2062
|
+
|
|
2063
|
+
EXAMPLES::
|
|
2064
|
+
|
|
2065
|
+
sage: r_version() # not tested
|
|
2066
|
+
((3, 0, 1), 'R version 3.0.1 (2013-05-16)')
|
|
2067
|
+
sage: rint, rstr = r_version()
|
|
2068
|
+
sage: rint[0] >= 3
|
|
2069
|
+
True
|
|
2070
|
+
sage: rstr.startswith('R version')
|
|
2071
|
+
True
|
|
2072
|
+
"""
|
|
2073
|
+
return r.version()
|
|
2074
|
+
|
|
2075
|
+
|
|
2076
|
+
class HelpExpression(str):
|
|
2077
|
+
"""
|
|
2078
|
+
Used to improve printing of output of r.help.
|
|
2079
|
+
"""
|
|
2080
|
+
def __repr__(self):
|
|
2081
|
+
r"""
|
|
2082
|
+
Return string representation of ``self``.
|
|
2083
|
+
|
|
2084
|
+
OUTPUT: string
|
|
2085
|
+
|
|
2086
|
+
EXAMPLES::
|
|
2087
|
+
|
|
2088
|
+
sage: a = sage.interfaces.r.HelpExpression("This\nis\nR!")
|
|
2089
|
+
sage: type(a)
|
|
2090
|
+
<class 'sage.interfaces.r.HelpExpression'>
|
|
2091
|
+
sage: a
|
|
2092
|
+
This
|
|
2093
|
+
is
|
|
2094
|
+
R!
|
|
2095
|
+
"""
|
|
2096
|
+
return str(self)
|