##// END OF EJS Templates
Merge pull request #5581 from takluyver/i5579...
Min RK -
r16254:73cfc9c6 merge
parent child Browse files
Show More
@@ -1,696 +1,696 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 ======
4 4 Rmagic
5 5 ======
6 6
7 7 Magic command interface for interactive work with R via rpy2
8 8
9 9 .. note::
10 10
11 11 The ``rpy2`` package needs to be installed separately. It
12 12 can be obtained using ``easy_install`` or ``pip``.
13 13
14 14 You will also need a working copy of R.
15 15
16 16 Usage
17 17 =====
18 18
19 19 To enable the magics below, execute ``%load_ext rmagic``.
20 20
21 21 ``%R``
22 22
23 23 {R_DOC}
24 24
25 25 ``%Rpush``
26 26
27 27 {RPUSH_DOC}
28 28
29 29 ``%Rpull``
30 30
31 31 {RPULL_DOC}
32 32
33 33 ``%Rget``
34 34
35 35 {RGET_DOC}
36 36
37 37 """
38 38 from __future__ import print_function
39 39
40 40 #-----------------------------------------------------------------------------
41 41 # Copyright (C) 2012 The IPython Development Team
42 42 #
43 43 # Distributed under the terms of the BSD License. The full license is in
44 44 # the file COPYING, distributed as part of this software.
45 45 #-----------------------------------------------------------------------------
46 46
47 47 import sys
48 48 import tempfile
49 49 from glob import glob
50 50 from shutil import rmtree
51 51
52 52 # numpy and rpy2 imports
53 53
54 54 import numpy as np
55 55
56 56 import rpy2.rinterface as ri
57 57 import rpy2.robjects as ro
58 58 try:
59 59 from rpy2.robjects import pandas2ri
60 60 pandas2ri.activate()
61 61 except ImportError:
62 62 pandas2ri = None
63 63 from rpy2.robjects import numpy2ri
64 64 numpy2ri.activate()
65 65
66 66 # IPython imports
67 67
68 68 from IPython.core.displaypub import publish_display_data
69 69 from IPython.core.magic import (Magics, magics_class, line_magic,
70 70 line_cell_magic, needs_local_scope)
71 71 from IPython.testing.skipdoctest import skip_doctest
72 72 from IPython.core.magic_arguments import (
73 73 argument, magic_arguments, parse_argstring
74 74 )
75 75 from IPython.external.simplegeneric import generic
76 76 from IPython.utils.py3compat import (str_to_unicode, unicode_to_str, PY3,
77 77 unicode_type)
78 78 from IPython.utils.text import dedent
79 79
80 80 class RInterpreterError(ri.RRuntimeError):
81 81 """An error when running R code in a %%R magic cell."""
82 82 def __init__(self, line, err, stdout):
83 83 self.line = line
84 84 self.err = err.rstrip()
85 85 self.stdout = stdout.rstrip()
86 86
87 87 def __unicode__(self):
88 88 s = 'Failed to parse and evaluate line %r.\nR error message: %r' % \
89 89 (self.line, self.err)
90 90 if self.stdout and (self.stdout != self.err):
91 91 s += '\nR stdout:\n' + self.stdout
92 92 return s
93 93
94 94 if PY3:
95 95 __str__ = __unicode__
96 96 else:
97 97 def __str__(self):
98 98 return unicode_to_str(unicode(self), 'utf-8')
99 99
100 100 def Rconverter(Robj, dataframe=False):
101 101 """
102 102 Convert an object in R's namespace to one suitable
103 103 for ipython's namespace.
104 104
105 105 For a data.frame, it tries to return a structured array.
106 106 It first checks for colnames, then names.
107 107 If all are NULL, it returns np.asarray(Robj), else
108 108 it tries to construct a recarray
109 109
110 110 Parameters
111 111 ----------
112 112
113 113 Robj: an R object returned from rpy2
114 114 """
115 115 is_data_frame = ro.r('is.data.frame')
116 116 colnames = ro.r('colnames')
117 117 rownames = ro.r('rownames') # with pandas, these could be used for the index
118 118 names = ro.r('names')
119 119
120 120 if dataframe:
121 121 as_data_frame = ro.r('as.data.frame')
122 122 cols = colnames(Robj)
123 123 _names = names(Robj)
124 124 if cols != ri.NULL:
125 125 Robj = as_data_frame(Robj)
126 126 names = tuple(np.array(cols))
127 127 elif _names != ri.NULL:
128 128 names = tuple(np.array(_names))
129 129 else: # failed to find names
130 130 return np.asarray(Robj)
131 131 Robj = np.rec.fromarrays(Robj, names = names)
132 132 return np.asarray(Robj)
133 133
134 134 @generic
135 135 def pyconverter(pyobj):
136 136 """Convert Python objects to R objects. Add types using the decorator:
137 137
138 138 @pyconverter.when_type
139 139 """
140 140 return pyobj
141 141
142 142 # The default conversion for lists seems to make them a nested list. That has
143 143 # some advantages, but is rarely convenient, so for interactive use, we convert
144 144 # lists to a numpy array, which becomes an R vector.
145 145 @pyconverter.when_type(list)
146 146 def pyconverter_list(pyobj):
147 147 return np.asarray(pyobj)
148 148
149 149 if pandas2ri is None:
150 150 # pandas2ri was new in rpy2 2.3.3, so for now we'll fallback to pandas'
151 151 # conversion function.
152 152 try:
153 153 from pandas import DataFrame
154 154 from pandas.rpy.common import convert_to_r_dataframe
155 155 @pyconverter.when_type(DataFrame)
156 156 def pyconverter_dataframe(pyobj):
157 157 return convert_to_r_dataframe(pyobj, strings_as_factors=True)
158 158 except ImportError:
159 159 pass
160 160
161 161 @magics_class
162 162 class RMagics(Magics):
163 163 """A set of magics useful for interactive work with R via rpy2.
164 164 """
165 165
166 166 def __init__(self, shell, Rconverter=Rconverter,
167 167 pyconverter=pyconverter,
168 168 cache_display_data=False):
169 169 """
170 170 Parameters
171 171 ----------
172 172
173 173 shell : IPython shell
174 174
175 175 Rconverter : callable
176 176 To be called on values taken from R before putting them in the
177 177 IPython namespace.
178 178
179 179 pyconverter : callable
180 180 To be called on values in ipython namespace before
181 181 assigning to variables in rpy2.
182 182
183 183 cache_display_data : bool
184 184 If True, the published results of the final call to R are
185 185 cached in the variable 'display_cache'.
186 186
187 187 """
188 188 super(RMagics, self).__init__(shell)
189 189 self.cache_display_data = cache_display_data
190 190
191 191 self.r = ro.R()
192 192
193 193 self.Rstdout_cache = []
194 194 self.pyconverter = pyconverter
195 195 self.Rconverter = Rconverter
196 196
197 197 def eval(self, line):
198 198 '''
199 199 Parse and evaluate a line of R code with rpy2.
200 200 Returns the output to R's stdout() connection,
201 201 the value generated by evaluating the code, and a
202 202 boolean indicating whether the return value would be
203 203 visible if the line of code were evaluated in an R REPL.
204 204
205 205 R Code evaluation and visibility determination are
206 206 done via an R call of the form withVisible({<code>})
207 207
208 208 '''
209 209 old_writeconsole = ri.get_writeconsole()
210 210 ri.set_writeconsole(self.write_console)
211 211 try:
212 res = ro.r("withVisible({%s})" % line)
212 res = ro.r("withVisible({%s\n})" % line)
213 213 value = res[0] #value (R object)
214 214 visible = ro.conversion.ri2py(res[1])[0] #visible (boolean)
215 215 except (ri.RRuntimeError, ValueError) as exception:
216 216 warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error
217 217 raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg)
218 218 text_output = self.flush()
219 219 ri.set_writeconsole(old_writeconsole)
220 220 return text_output, value, visible
221 221
222 222 def write_console(self, output):
223 223 '''
224 224 A hook to capture R's stdout in a cache.
225 225 '''
226 226 self.Rstdout_cache.append(output)
227 227
228 228 def flush(self):
229 229 '''
230 230 Flush R's stdout cache to a string, returning the string.
231 231 '''
232 232 value = ''.join([str_to_unicode(s, 'utf-8') for s in self.Rstdout_cache])
233 233 self.Rstdout_cache = []
234 234 return value
235 235
236 236 @skip_doctest
237 237 @needs_local_scope
238 238 @line_magic
239 239 def Rpush(self, line, local_ns=None):
240 240 '''
241 241 A line-level magic for R that pushes
242 242 variables from python to rpy2. The line should be made up
243 243 of whitespace separated variable names in the IPython
244 244 namespace::
245 245
246 246 In [7]: import numpy as np
247 247
248 248 In [8]: X = np.array([4.5,6.3,7.9])
249 249
250 250 In [9]: X.mean()
251 251 Out[9]: 6.2333333333333343
252 252
253 253 In [10]: %Rpush X
254 254
255 255 In [11]: %R mean(X)
256 256 Out[11]: array([ 6.23333333])
257 257
258 258 '''
259 259 if local_ns is None:
260 260 local_ns = {}
261 261
262 262 inputs = line.split(' ')
263 263 for input in inputs:
264 264 try:
265 265 val = local_ns[input]
266 266 except KeyError:
267 267 try:
268 268 val = self.shell.user_ns[input]
269 269 except KeyError:
270 270 # reraise the KeyError as a NameError so that it looks like
271 271 # the standard python behavior when you use an unnamed
272 272 # variable
273 273 raise NameError("name '%s' is not defined" % input)
274 274
275 275 self.r.assign(input, self.pyconverter(val))
276 276
277 277 @skip_doctest
278 278 @magic_arguments()
279 279 @argument(
280 280 '-d', '--as_dataframe', action='store_true',
281 281 default=False,
282 282 help='Convert objects to data.frames before returning to ipython.'
283 283 )
284 284 @argument(
285 285 'outputs',
286 286 nargs='*',
287 287 )
288 288 @line_magic
289 289 def Rpull(self, line):
290 290 '''
291 291 A line-level magic for R that pulls
292 292 variables from python to rpy2::
293 293
294 294 In [18]: _ = %R x = c(3,4,6.7); y = c(4,6,7); z = c('a',3,4)
295 295
296 296 In [19]: %Rpull x y z
297 297
298 298 In [20]: x
299 299 Out[20]: array([ 3. , 4. , 6.7])
300 300
301 301 In [21]: y
302 302 Out[21]: array([ 4., 6., 7.])
303 303
304 304 In [22]: z
305 305 Out[22]:
306 306 array(['a', '3', '4'],
307 307 dtype='|S1')
308 308
309 309
310 310 If --as_dataframe, then each object is returned as a structured array
311 311 after first passed through "as.data.frame" in R before
312 312 being calling self.Rconverter.
313 313 This is useful when a structured array is desired as output, or
314 314 when the object in R has mixed data types.
315 315 See the %%R docstring for more examples.
316 316
317 317 Notes
318 318 -----
319 319
320 320 Beware that R names can have '.' so this is not fool proof.
321 321 To avoid this, don't name your R objects with '.'s...
322 322
323 323 '''
324 324 args = parse_argstring(self.Rpull, line)
325 325 outputs = args.outputs
326 326 for output in outputs:
327 327 self.shell.push({output:self.Rconverter(self.r(output),dataframe=args.as_dataframe)})
328 328
329 329 @skip_doctest
330 330 @magic_arguments()
331 331 @argument(
332 332 '-d', '--as_dataframe', action='store_true',
333 333 default=False,
334 334 help='Convert objects to data.frames before returning to ipython.'
335 335 )
336 336 @argument(
337 337 'output',
338 338 nargs=1,
339 339 type=str,
340 340 )
341 341 @line_magic
342 342 def Rget(self, line):
343 343 '''
344 344 Return an object from rpy2, possibly as a structured array (if possible).
345 345 Similar to Rpull except only one argument is accepted and the value is
346 346 returned rather than pushed to self.shell.user_ns::
347 347
348 348 In [3]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
349 349
350 350 In [4]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
351 351
352 352 In [5]: %R -i datapy
353 353
354 354 In [6]: %Rget datapy
355 355 Out[6]:
356 356 array([['1', '2', '3', '4'],
357 357 ['2', '3', '2', '5'],
358 358 ['a', 'b', 'c', 'e']],
359 359 dtype='|S1')
360 360
361 361 In [7]: %Rget -d datapy
362 362 Out[7]:
363 363 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
364 364 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
365 365
366 366 '''
367 367 args = parse_argstring(self.Rget, line)
368 368 output = args.output
369 369 return self.Rconverter(self.r(output[0]),dataframe=args.as_dataframe)
370 370
371 371
372 372 @skip_doctest
373 373 @magic_arguments()
374 374 @argument(
375 375 '-i', '--input', action='append',
376 376 help='Names of input variable from shell.user_ns to be assigned to R variables of the same names after calling self.pyconverter. Multiple names can be passed separated only by commas with no whitespace.'
377 377 )
378 378 @argument(
379 379 '-o', '--output', action='append',
380 380 help='Names of variables to be pushed from rpy2 to shell.user_ns after executing cell body and applying self.Rconverter. Multiple names can be passed separated only by commas with no whitespace.'
381 381 )
382 382 @argument(
383 383 '-w', '--width', type=int,
384 384 help='Width of png plotting device sent as an argument to *png* in R.'
385 385 )
386 386 @argument(
387 387 '-h', '--height', type=int,
388 388 help='Height of png plotting device sent as an argument to *png* in R.'
389 389 )
390 390
391 391 @argument(
392 392 '-d', '--dataframe', action='append',
393 393 help='Convert these objects to data.frames and return as structured arrays.'
394 394 )
395 395 @argument(
396 396 '-u', '--units', type=unicode_type, choices=["px", "in", "cm", "mm"],
397 397 help='Units of png plotting device sent as an argument to *png* in R. One of ["px", "in", "cm", "mm"].'
398 398 )
399 399 @argument(
400 400 '-r', '--res', type=int,
401 401 help='Resolution of png plotting device sent as an argument to *png* in R. Defaults to 72 if *units* is one of ["in", "cm", "mm"].'
402 402 )
403 403 @argument(
404 404 '-p', '--pointsize', type=int,
405 405 help='Pointsize of png plotting device sent as an argument to *png* in R.'
406 406 )
407 407 @argument(
408 408 '-b', '--bg',
409 409 help='Background of png plotting device sent as an argument to *png* in R.'
410 410 )
411 411 @argument(
412 412 '-n', '--noreturn',
413 413 help='Force the magic to not return anything.',
414 414 action='store_true',
415 415 default=False
416 416 )
417 417 @argument(
418 418 'code',
419 419 nargs='*',
420 420 )
421 421 @needs_local_scope
422 422 @line_cell_magic
423 423 def R(self, line, cell=None, local_ns=None):
424 424 '''
425 425 Execute code in R, and pull some of the results back into the Python namespace.
426 426
427 427 In line mode, this will evaluate an expression and convert the returned value to a Python object.
428 428 The return value is determined by rpy2's behaviour of returning the result of evaluating the
429 429 final line.
430 430
431 431 Multiple R lines can be executed by joining them with semicolons::
432 432
433 433 In [9]: %R X=c(1,4,5,7); sd(X); mean(X)
434 434 Out[9]: array([ 4.25])
435 435
436 436 In cell mode, this will run a block of R code. The resulting value
437 437 is printed if it would printed be when evaluating the same code
438 438 within a standard R REPL.
439 439
440 440 Nothing is returned to python by default in cell mode::
441 441
442 442 In [10]: %%R
443 443 ....: Y = c(2,4,3,9)
444 444 ....: summary(lm(Y~X))
445 445
446 446 Call:
447 447 lm(formula = Y ~ X)
448 448
449 449 Residuals:
450 450 1 2 3 4
451 451 0.88 -0.24 -2.28 1.64
452 452
453 453 Coefficients:
454 454 Estimate Std. Error t value Pr(>|t|)
455 455 (Intercept) 0.0800 2.3000 0.035 0.975
456 456 X 1.0400 0.4822 2.157 0.164
457 457
458 458 Residual standard error: 2.088 on 2 degrees of freedom
459 459 Multiple R-squared: 0.6993,Adjusted R-squared: 0.549
460 460 F-statistic: 4.651 on 1 and 2 DF, p-value: 0.1638
461 461
462 462 In the notebook, plots are published as the output of the cell::
463 463
464 464 %R plot(X, Y)
465 465
466 466 will create a scatter plot of X bs Y.
467 467
468 468 If cell is not None and line has some R code, it is prepended to
469 469 the R code in cell.
470 470
471 471 Objects can be passed back and forth between rpy2 and python via the -i -o flags in line::
472 472
473 473 In [14]: Z = np.array([1,4,5,10])
474 474
475 475 In [15]: %R -i Z mean(Z)
476 476 Out[15]: array([ 5.])
477 477
478 478
479 479 In [16]: %R -o W W=Z*mean(Z)
480 480 Out[16]: array([ 5., 20., 25., 50.])
481 481
482 482 In [17]: W
483 483 Out[17]: array([ 5., 20., 25., 50.])
484 484
485 485 The return value is determined by these rules:
486 486
487 487 * If the cell is not None, the magic returns None.
488 488
489 489 * If the cell evaluates as False, the resulting value is returned
490 490 unless the final line prints something to the console, in
491 491 which case None is returned.
492 492
493 493 * If the final line results in a NULL value when evaluated
494 494 by rpy2, then None is returned.
495 495
496 496 * No attempt is made to convert the final value to a structured array.
497 497 Use the --dataframe flag or %Rget to push / return a structured array.
498 498
499 499 * If the -n flag is present, there is no return value.
500 500
501 501 * A trailing ';' will also result in no return value as the last
502 502 value in the line is an empty string.
503 503
504 504 The --dataframe argument will attempt to return structured arrays.
505 505 This is useful for dataframes with
506 506 mixed data types. Note also that for a data.frame,
507 507 if it is returned as an ndarray, it is transposed::
508 508
509 509 In [18]: dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')]
510 510
511 511 In [19]: datapy = np.array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5, 'e')], dtype=dtype)
512 512
513 513 In [20]: %%R -o datar
514 514 datar = datapy
515 515 ....:
516 516
517 517 In [21]: datar
518 518 Out[21]:
519 519 array([['1', '2', '3', '4'],
520 520 ['2', '3', '2', '5'],
521 521 ['a', 'b', 'c', 'e']],
522 522 dtype='|S1')
523 523
524 524 In [22]: %%R -d datar
525 525 datar = datapy
526 526 ....:
527 527
528 528 In [23]: datar
529 529 Out[23]:
530 530 array([(1, 2.9, 'a'), (2, 3.5, 'b'), (3, 2.1, 'c'), (4, 5.0, 'e')],
531 531 dtype=[('x', '<i4'), ('y', '<f8'), ('z', '|S1')])
532 532
533 533 The --dataframe argument first tries colnames, then names.
534 534 If both are NULL, it returns an ndarray (i.e. unstructured)::
535 535
536 536 In [1]: %R mydata=c(4,6,8.3); NULL
537 537
538 538 In [2]: %R -d mydata
539 539
540 540 In [3]: mydata
541 541 Out[3]: array([ 4. , 6. , 8.3])
542 542
543 543 In [4]: %R names(mydata) = c('a','b','c'); NULL
544 544
545 545 In [5]: %R -d mydata
546 546
547 547 In [6]: mydata
548 548 Out[6]:
549 549 array((4.0, 6.0, 8.3),
550 550 dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
551 551
552 552 In [7]: %R -o mydata
553 553
554 554 In [8]: mydata
555 555 Out[8]: array([ 4. , 6. , 8.3])
556 556
557 557 '''
558 558
559 559 args = parse_argstring(self.R, line)
560 560
561 561 # arguments 'code' in line are prepended to
562 562 # the cell lines
563 563
564 564 if cell is None:
565 565 code = ''
566 566 return_output = True
567 567 line_mode = True
568 568 else:
569 569 code = cell
570 570 return_output = False
571 571 line_mode = False
572 572
573 573 code = ' '.join(args.code) + code
574 574
575 575 # if there is no local namespace then default to an empty dict
576 576 if local_ns is None:
577 577 local_ns = {}
578 578
579 579 if args.input:
580 580 for input in ','.join(args.input).split(','):
581 581 try:
582 582 val = local_ns[input]
583 583 except KeyError:
584 584 try:
585 585 val = self.shell.user_ns[input]
586 586 except KeyError:
587 587 raise NameError("name '%s' is not defined" % input)
588 588 self.r.assign(input, self.pyconverter(val))
589 589
590 590 if getattr(args, 'units') is not None:
591 591 if args.units != "px" and getattr(args, 'res') is None:
592 592 args.res = 72
593 593 args.units = '"%s"' % args.units
594 594
595 595 png_argdict = dict([(n, getattr(args, n)) for n in ['units', 'res', 'height', 'width', 'bg', 'pointsize']])
596 596 png_args = ','.join(['%s=%s' % (o,v) for o, v in png_argdict.items() if v is not None])
597 597 # execute the R code in a temporary directory
598 598
599 599 tmpd = tempfile.mkdtemp()
600 600 self.r('png("%s/Rplots%%03d.png",%s)' % (tmpd.replace('\\', '/'), png_args))
601 601
602 602 text_output = ''
603 603 try:
604 604 if line_mode:
605 605 for line in code.split(';'):
606 606 text_result, result, visible = self.eval(line)
607 607 text_output += text_result
608 608 if text_result:
609 609 # the last line printed something to the console so we won't return it
610 610 return_output = False
611 611 else:
612 612 text_result, result, visible = self.eval(code)
613 613 text_output += text_result
614 614 if visible:
615 615 old_writeconsole = ri.get_writeconsole()
616 616 ri.set_writeconsole(self.write_console)
617 617 ro.r.show(result)
618 618 text_output += self.flush()
619 619 ri.set_writeconsole(old_writeconsole)
620 620
621 621 except RInterpreterError as e:
622 622 print(e.stdout)
623 623 if not e.stdout.endswith(e.err):
624 624 print(e.err)
625 625 rmtree(tmpd)
626 626 return
627 627
628 628 self.r('dev.off()')
629 629
630 630 # read out all the saved .png files
631 631
632 632 images = [open(imgfile, 'rb').read() for imgfile in glob("%s/Rplots*png" % tmpd)]
633 633
634 634 # now publish the images
635 635 # mimicking IPython/zmq/pylab/backend_inline.py
636 636 fmt = 'png'
637 637 mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
638 638 mime = mimetypes[fmt]
639 639
640 640 # publish the printed R objects, if any
641 641
642 642 display_data = []
643 643 if text_output:
644 644 display_data.append(('RMagic.R', {'text/plain':text_output}))
645 645
646 646 # flush text streams before sending figures, helps a little with output
647 647 for image in images:
648 648 # synchronization in the console (though it's a bandaid, not a real sln)
649 649 sys.stdout.flush(); sys.stderr.flush()
650 650 display_data.append(('RMagic.R', {mime: image}))
651 651
652 652 # kill the temporary directory
653 653 rmtree(tmpd)
654 654
655 655 # try to turn every output into a numpy array
656 656 # this means that output are assumed to be castable
657 657 # as numpy arrays
658 658
659 659 if args.output:
660 660 for output in ','.join(args.output).split(','):
661 661 self.shell.push({output:self.Rconverter(self.r(output), dataframe=False)})
662 662
663 663 if args.dataframe:
664 664 for output in ','.join(args.dataframe).split(','):
665 665 self.shell.push({output:self.Rconverter(self.r(output), dataframe=True)})
666 666
667 667 for tag, disp_d in display_data:
668 668 publish_display_data(tag, disp_d)
669 669
670 670 # this will keep a reference to the display_data
671 671 # which might be useful to other objects who happen to use
672 672 # this method
673 673
674 674 if self.cache_display_data:
675 675 self.display_cache = display_data
676 676
677 677 # if in line mode and return_output, return the result as an ndarray
678 678 if return_output and not args.noreturn:
679 679 if result != ri.NULL:
680 680 return self.Rconverter(result, dataframe=False)
681 681
682 682 __doc__ = __doc__.format(
683 683 R_DOC = dedent(RMagics.R.__doc__),
684 684 RPUSH_DOC = dedent(RMagics.Rpush.__doc__),
685 685 RPULL_DOC = dedent(RMagics.Rpull.__doc__),
686 686 RGET_DOC = dedent(RMagics.Rget.__doc__)
687 687 )
688 688
689 689
690 690 def load_ipython_extension(ip):
691 691 """Load the extension in IPython."""
692 692 ip.register_magics(RMagics)
693 693 # Initialising rpy2 interferes with readline. Since, at this point, we've
694 694 # probably just loaded rpy2, we reset the delimiters. See issue gh-2759.
695 695 if ip.has_readline:
696 696 ip.readline.set_completer_delims(ip.readline_delims)
General Comments 0
You need to be logged in to leave comments. Login now