##// END OF EJS Templates
Merge pull request #2889 from takluyver/r-dataframe...
Thomas Kluyver -
r10148:64e38f24 merge
parent child Browse files
Show More
@@ -46,8 +46,13 b' import numpy as np'
46
46
47 import rpy2.rinterface as ri
47 import rpy2.rinterface as ri
48 import rpy2.robjects as ro
48 import rpy2.robjects as ro
49 from rpy2.robjects.numpy2ri import numpy2ri
49 try:
50 ro.conversion.py2ri = numpy2ri
50 from rpy2.robjects import pandas2ri
51 pandas2ri.activate()
52 except ImportError:
53 pandas2ri = None
54 from rpy2.robjects import numpy2ri
55 numpy2ri.activate()
51
56
52 # IPython imports
57 # IPython imports
53
58
@@ -58,6 +63,7 b' from IPython.testing.skipdoctest import skip_doctest'
58 from IPython.core.magic_arguments import (
63 from IPython.core.magic_arguments import (
59 argument, magic_arguments, parse_argstring
64 argument, magic_arguments, parse_argstring
60 )
65 )
66 from IPython.external.simplegeneric import generic
61 from IPython.utils.py3compat import str_to_unicode, unicode_to_str, PY3
67 from IPython.utils.py3compat import str_to_unicode, unicode_to_str, PY3
62
68
63 class RInterpreterError(ri.RRuntimeError):
69 class RInterpreterError(ri.RRuntimeError):
@@ -114,19 +120,50 b' def Rconverter(Robj, dataframe=False):'
114 Robj = np.rec.fromarrays(Robj, names = names)
120 Robj = np.rec.fromarrays(Robj, names = names)
115 return np.asarray(Robj)
121 return np.asarray(Robj)
116
122
123 @generic
124 def pyconverter(pyobj):
125 """Convert Python objects to R objects. Add types using the decorator:
126
127 @pyconverter.when_type
128 """
129 return pyobj
130
131 # The default conversion for lists seems to make them a nested list. That has
132 # some advantages, but is rarely convenient, so for interactive use, we convert
133 # lists to a numpy array, which becomes an R vector.
134 @pyconverter.when_type(list)
135 def pyconverter_list(pyobj):
136 return np.asarray(pyobj)
137
138 if pandas2ri is None:
139 # pandas2ri was new in rpy2 2.3.3, so for now we'll fallback to pandas'
140 # conversion function.
141 try:
142 from pandas import DataFrame
143 from pandas.rpy.common import convert_to_r_dataframe
144 @pyconverter.when_type(DataFrame)
145 def pyconverter_dataframe(pyobj):
146 return convert_to_r_dataframe(pyobj, strings_as_factors=True)
147 except ImportError:
148 pass
149
117 @magics_class
150 @magics_class
118 class RMagics(Magics):
151 class RMagics(Magics):
119 """A set of magics useful for interactive work with R via rpy2.
152 """A set of magics useful for interactive work with R via rpy2.
120 """
153 """
121
154
122 def __init__(self, shell, Rconverter=Rconverter,
155 def __init__(self, shell, Rconverter=Rconverter,
123 pyconverter=np.asarray,
156 pyconverter=pyconverter,
124 cache_display_data=False):
157 cache_display_data=False):
125 """
158 """
126 Parameters
159 Parameters
127 ----------
160 ----------
128
161
129 shell : IPython shell
162 shell : IPython shell
163
164 Rconverter : callable
165 To be called on values taken from R before putting them in the
166 IPython namespace.
130
167
131 pyconverter : callable
168 pyconverter : callable
132 To be called on values in ipython namespace before
169 To be called on values in ipython namespace before
@@ -1,6 +1,10 b''
1 from StringIO import StringIO
2
1 import numpy as np
3 import numpy as np
2 from IPython.core.interactiveshell import InteractiveShell
4 from IPython.core.interactiveshell import InteractiveShell
5 from IPython.testing.decorators import skip_without
3 from IPython.extensions import rmagic
6 from IPython.extensions import rmagic
7 from rpy2 import rinterface
4 import nose.tools as nt
8 import nose.tools as nt
5
9
6 ip = get_ipython()
10 ip = get_ipython()
@@ -28,6 +32,29 b' result = rmagic_addone(12344)'
28 result = ip.user_ns['result']
32 result = ip.user_ns['result']
29 np.testing.assert_equal(result, 12345)
33 np.testing.assert_equal(result, 12345)
30
34
35 @skip_without('pandas')
36 def test_push_dataframe():
37 from pandas import DataFrame
38 rm = rmagic.RMagics(ip)
39 df = DataFrame([{'a': 1, 'b': 'bar'}, {'a': 5, 'b': 'foo', 'c': 20}])
40 ip.push({'df':df})
41 ip.run_line_magic('Rpush', 'df')
42
43 # This is converted to factors, which are currently converted back to Python
44 # as integers, so for now we test its representation in R.
45 sio = StringIO()
46 rinterface.set_writeconsole(sio.write)
47 try:
48 rm.r('print(df$b[1])')
49 nt.assert_in('[1] bar', sio.getvalue())
50 finally:
51 rinterface.set_writeconsole(None)
52
53 # Values come packaged in arrays, so we unbox them to test.
54 nt.assert_equal(rm.r('df$a[2]')[0], 5)
55 missing = rm.r('df$c[1]')[0]
56 assert np.isnan(missing), missing
57
31 def test_pull():
58 def test_pull():
32 rm = rmagic.RMagics(ip)
59 rm = rmagic.RMagics(ip)
33 rm.r('Z=c(11:20)')
60 rm.r('Z=c(11:20)')
@@ -50,7 +77,7 b' def test_Rconverter():'
50 np.testing.assert_equal(id(w.data), id(v.data))
77 np.testing.assert_equal(id(w.data), id(v.data))
51 nt.assert_equal(w.dtype, v.dtype)
78 nt.assert_equal(w.dtype, v.dtype)
52
79
53 ip.run_cell_magic('R', ' -d datar datar=datapy', '')
80 ip.run_cell_magic('R', ' -d datar', 'datar=datapy')
54
81
55 u = ip.run_line_magic('Rget', ' -d datar')
82 u = ip.run_line_magic('Rget', ' -d datar')
56 np.testing.assert_almost_equal(u['x'], v['x'])
83 np.testing.assert_almost_equal(u['x'], v['x'])
General Comments 0
You need to be logged in to leave comments. Login now