def test_init_From_seq_invalid_elt(): seq = (ri.FloatSexpVector([1.0]), lambda x: x, ri.StrSexpVector(['foo', 'bar'])) with pytest.raises(Exception): ri.ListSexpVector(seq)
def testGetItemExpression(self): expression = ri.baseenv.get('expression') e = expression(ri.StrSexpVector(['a', ]), ri.StrSexpVector(['b', ])) y = e[0] self.assertEqual(ri.STRSXP, y.typeof)
def testSetSliceStr(self): vec = ri.StrSexpVector(['a','b','c']) vec[0:2] = ri.StrSexpVector(['d','e']) self.assertEqual(3, len(vec)) self.assertEqual('d', vec[0]) self.assertEqual('e', vec[1])
def testNACharactertoR(self): na_character = ri.NACharacterType() self.assertEqual(True, ri.baseenv["is.na"](ri.StrSexpVector((na_character, )))[0])
def testStr(self): sexp = ri.StrSexpVector(["a", ]) isStr = ri.globalenv.get("is.character") ok = isStr(sexp)[0] self.assertTrue(ok)
def test_setslice(): vec = ri.StrSexpVector(['foo', 'bar', 'baz']) vec[0:2] = ['boo', 'noo'] assert len(vec) == 3 assert vec[0] == 'boo' assert vec[1] == 'noo'
from operator import attrgetter import warnings from rpy2.rinterface import (Sexp, ListSexpVector, StrSexpVector, IntSexpVector, ByteSexpVector, BoolSexpVector, ComplexSexpVector, FloatSexpVector, NA_Real, NA_Integer, NA_Character, NA_Logical, NULL, MissingArg) globalenv_ri = rinterface.globalenv baseenv_ri = rinterface.baseenv r_concat = baseenv_ri['c'] as_character = baseenv_ri['as.character'] utils_ri = baseenv_ri['as.environment']( rinterface.StrSexpVector(("package:utils", )) ) # The default timezone can be used for time or datetime objects. default_timezone = None class ExtractDelegator(object): """ Delegate the R 'extraction' ("[") and 'replacement' ("[<-") of items in a vector or vector-like object. This can help making syntactic niceties possible.""" _extractfunction = rinterface.baseenv['['] _replacefunction = rinterface.baseenv['[<-']
def test_str(): sexp = ri.StrSexpVector(["a", ]) isStr = ri.globalenv.find("is.character") assert isStr(sexp)[0]
def test_rclass_set_invalid(): sexp = rinterface.IntSexpVector([1, 2, 3]) with pytest.raises(TypeError): sexp.rclass = rinterface.StrSexpVector(123)
def _(obj): res = rinterface.ListSexpVector([conversion.py2ri(x) for x in obj]) res.do_slot_assign('names', rinterface.StrSexpVector(obj.tags)) return res
def _1(obj): keys = list(obj.keys()) res = rinterface.ListSexpVector( [conversion.py2ri(obj[x]) for x in keys]) res.do_slot_assign('names', rinterface.StrSexpVector(keys)) return res
def test_from_pyobject_protected(): pyobject = 'ahaha' sexp_new = (rinterface.SexpExtPtr.from_pyobject( pyobject, protected=rinterface.StrSexpVector("c"))) assert sexp_new.typeof == rinterface.RTYPES.EXTPTRSXP assert sexp_new.__protected__[0] == 'c'
def testSexp_sexp_wrongtypeof(self): sexp = rinterface.IntSexpVector([1, 2, 3]) cobj = sexp.__sexp__ sexp = rinterface.StrSexpVector(['a', 'b']) self.assertEqual(2, len(sexp)) self.assertRaises(ValueError, sexp.__setattr__, '__sexp__', cobj)
def testSexp_rclass_set(self): sexp = rinterface.IntSexpVector([1, 2, 3]) sexp.rclass = rinterface.StrSexpVector(['foo']) self.assertEqual(len(sexp.rclass), 1) self.assertEqual(sexp.rclass[0], "foo")
def test_getslice(): vec = ri.StrSexpVector(['foo', 'bar', 'baz']) vec_s = vec[0:2] assert len(vec_s) == 2 assert vec_s[0] == 'foo' assert vec_s[1] == 'bar'
def test_names_set(): sexp = rinterface.IntSexpVector([1, 2, 3]) assert sexp.names.rid == rinterface.NULL.rid sexp.names = rinterface.StrSexpVector(['a', 'b', 'c']) assert len(sexp.names) > 1 assert tuple(sexp.names) == ('a', 'b', 'c')
def test_getslice_negative(): vec = ri.StrSexpVector(['foo', 'bar', 'baz']) vec_s = vec[-2:-1] assert len(vec_s) == 1 assert vec_s[0] == 'bar'
def get_packagepath(package): """ return the path to an R package installed """ res = _find_package(rinterface.StrSexpVector((package, ))) return res[0]
def test_init_from_seqr(): seq = ['foo', 'bar', 'baz'] v = ri.StrSexpVector(seq) assert len(v) == 3 for x, y in zip(seq, v): assert x == y
def importr(name, lib_loc=None, robject_translations={}, signature_translation=True, suppress_messages=True, on_conflict='fail', symbol_r2python=default_symbol_r2python, symbol_resolve=default_symbol_resolve, data=True): """ Import an R package. Arguments: - name: name of the R package - lib_loc: specific location for the R library (default: None) - robject_translations: dict (default: {}) - signature_translation: (True or False) - suppress_message: Suppress messages R usually writes on the console (defaut: True) - on_conflict: 'fail' or 'warn' (default: 'fail') - symbol_r2python: function to translate R symbols into Python symbols - symbol_resolve: function to check the Python symbol obtained from `symbol_r2python`. - data: embed a PackageData objects under the attribute name __rdata__ (default: True) Return: - an instance of class SignatureTranslatedPackage, or of class Package """ if not isinstalled(name): raise PackageNotInstalledError(name) if suppress_messages: ok = quiet_require(name, lib_loc=lib_loc) else: ok = _require(name, **{'lib.loc': rinterface.StrSexpVector((lib_loc, ))})[0] if not ok: raise LibraryError("The R package %s could not be imported" % name) if _package_has_namespace(name, _system_file(package=name)): env = _get_namespace(name) version = _get_namespace_version(name)[0] exported_names = set(_get_namespace_exports(name)) else: env = _as_env(rinterface.StrSexpVector([ 'package:' + name, ])) exported_names = None version = None if signature_translation: pack = InstalledSTPackage(env, name, translation=robject_translations, exported_names=exported_names, on_conflict=on_conflict, version=version, symbol_r2python=symbol_r2python, symbol_resolve=symbol_resolve) else: pack = InstalledPackage(env, name, translation=robject_translations, exported_names=exported_names, on_conflict=on_conflict, version=version, symbol_r2python=symbol_r2python, symbol_resolve=symbol_resolve) if data: if pack.__rdata__ is not None: warn('While importing the R package "%s", the rpy2 Package object ' 'is masking a translated R symbol "__rdata__" already present' % name) pack.__rdata__ = PackageData(name, lib_loc=lib_loc) return pack
class DataFrame(ListVector): """ R 'data.frame'. """ _dataframe_name = rinterface.StrSexpVector(('data.frame',)) _read_csv = utils_ri['read.csv'] _write_table = utils_ri['write.table'] _cbind = rinterface.baseenv['cbind.data.frame'] _rbind = rinterface.baseenv['rbind.data.frame'] _is_list = rinterface.baseenv['is.list'] _html_template = jinja2.Template( """ <span>R/rpy2 DataFrame ({{ nrows }} x {{ ncolumns }})</span> <table> <thead> <tr> {% for name in column_names %} <th>{{ name }}</th> {% endfor %} </tr> </thead> <tbody> {% for row_i in rows %} <tr> {% for col_i in columns %} <td> {{ elements[col_i][row_i] }} </td> {% endfor %} </tr> {% endfor %} </tbody> </table> """) def __init__(self, obj, stringsasfactor=False): """ Create a new data frame. :param obj: object inheriting from rpy2.rinterface.SexpVector, or inheriting from TaggedList or a mapping name -> value :param stringsasfactors: Boolean indicating whether vectors of strings should be turned to vectors. Note that factors will not be turned to string vectors. """ if isinstance(obj, rinterface.ListSexpVector): if obj.typeof != rinterface.RTYPES.VECSXP: raise ValueError( "obj should of typeof RTYPES.VECSXP " " (and we get %s)" % rinterface.RTYPES(obj.typeof) ) if ( self._is_list(obj)[0] or globalenv_ri.find('inherits')( obj, self._dataframe_name )[0] ): # TODO: is it really a good idea to pass R lists # to the constructor ? super().__init__(obj) return else: raise ValueError( "When passing R objects to build a DataFrame, " "the R object must be a list or inherit from " "the R class 'data.frame'." ) elif isinstance(obj, rlc.TaggedList): kv = [(k, conversion.py2rpy(v)) for k, v in obj.items()] else: try: kv = [(str(k), conversion.py2rpy(v)) for k, v in obj.items()] except AttributeError: raise ValueError( 'obj can only be' 'an instance of rpy2.rinterface.ListSexpVector, ' 'an instance of TaggedList, ' 'or an objects with a methods items() that returns ' '(key, value) pairs ' '(such a Python dict, rpy2.rlike.container OrdDict).') # Check if there is a conflicting column name if 'stringsAsFactors' in (k for k, v in kv): warnings.warn('The column name "stringsAsFactors" is ' 'conflicting with named parameter ' 'in underlying R function "data.frame()".') else: kv.append(('stringsAsFactors', stringsasfactor)) # Call R's data frame constructor kv = tuple(kv) df = baseenv_ri.find("data.frame").rcall(kv, globalenv_ri) super().__init__(df) def _repr_html_(self, max_items=7): names = list() if len(self) <= max_items: names.extend(self.names) else: half_items = max_items // 2 for i in range(0, half_items): try: name = self.names[i] except TypeError: name = '[no name]' names.append(name) names.append('...') for i in range(-half_items, 0): try: name = self.names[i] except TypeError: name = '[no name]' names.append(name) elements = list() for e in self._iter_repr(max_items=max_items): if hasattr(e, '_repr_html_'): elements.append(tuple(e._iter_formatted())) else: elements.append(['...', ]) d = {'column_names': names, 'rows': range(len(elements[0]) if len(elements) else 0), 'columns': tuple(range(len(names))), 'nrows': self.nrow, 'ncolumns': self.ncol, 'elements': elements} html = self._html_template.render(d) return html def _get_nrow(self): """ Number of rows. :rtype: integer """ return baseenv_ri["nrow"](self)[0] nrow = property(_get_nrow, None, None) def _get_ncol(self): """ Number of columns. :rtype: integer """ return baseenv_ri["ncol"](self)[0] ncol = property(_get_ncol, None, None) def _get_rownames(self): res = baseenv_ri["rownames"](self) return conversion.rpy2py(res) def _set_rownames(self, rownames): res = baseenv_ri["rownames<-"](self, conversion.py2rpy(rownames)) self.__sexp__ = res.__sexp__ rownames = property(_get_rownames, _set_rownames, None, 'Row names') def _get_colnames(self): res = baseenv_ri["colnames"](self) return conversion.rpy2py(res) def _set_colnames(self, colnames): res = baseenv_ri["colnames<-"](self, conversion.py2rpy(colnames)) self.__sexp__ = res.__sexp__ colnames = property(_get_colnames, _set_colnames, None) def __getitem__(self, i): # Make sure this is not a List returned # 3rd-party conversions could return objects # that no longer inherit from rpy2's R objects. # We need to use the low-level __getitem__ # to bypass the conversion mechanism. # R's data.frames have no representation at the C-API level # (they are lists) tmp = rinterface.ListSexpVector.__getitem__(self, i) if tmp.typeof == rinterface.RTYPES.VECSXP: return DataFrame(tmp) else: return conversion.rpy2py(tmp) def cbind(self, *args, **kwargs): """ bind objects as supplementary columns """ new_args = [self, ] + [conversion.rpy2py(x) for x in args] new_kwargs = dict( [(k, conversion.rpy2py(v)) for k, v in kwargs.items()] ) res = self._cbind(*new_args, **new_kwargs) return conversion.rpy2py(res) def rbind(self, *args, **kwargs): """ bind objects as supplementary rows """ new_args = [conversion.rpy2py(x) for x in args] new_kwargs = dict( [(k, conversion.rpy2py(v)) for k, v in kwargs.items()] ) res = self._rbind(self, *new_args, **new_kwargs) return conversion.rpy2py(res) def head(self, *args, **kwargs): """ Call the R generic 'head()'. """ res = utils_ri['head'](self, *args, **kwargs) return conversion.rpy2py(res) @staticmethod def from_csvfile(path, header=True, sep=',', quote='"', dec='.', row_names=rinterface.MissingArg, col_names=rinterface.MissingArg, fill=True, comment_char='', na_strings=[], as_is=False): """ Create an instance from data in a .csv file. :param path: string with a path :param header: boolean (heading line with column names or not) :param sep: separator character :param quote: quote character :param row_names: column name, or column index for column names (warning: indexing starts at one in R) :param fill: boolean (fill the lines when less entries than columns) :param comment_char: comment character :param na_strings: a list of strings which are interpreted to be NA values :param as_is: boolean (keep the columns of strings as such, or turn them into factors) """ path = conversion.py2rpy(path) header = conversion.py2rpy(header) sep = conversion.py2rpy(sep) quote = conversion.py2rpy(quote) dec = conversion.py2rpy(dec) if row_names is not rinterface.MissingArg: row_names = conversion.py2rpy(row_names) if col_names is not rinterface.MissingArg: col_names = conversion.py2rpy(col_names) fill = conversion.py2rpy(fill) comment_char = conversion.py2rpy(comment_char) as_is = conversion.py2rpy(as_is) na_strings = conversion.py2rpy(na_strings) res = DataFrame._read_csv(path, **{'header': header, 'sep': sep, 'quote': quote, 'dec': dec, 'row.names': row_names, 'col.names': col_names, 'fill': fill, 'comment.char': comment_char, 'na.strings': na_strings, 'as.is': as_is}) res = conversion.rpy2py(res) return res def to_csvfile(self, path, quote=True, sep=',', eol=os.linesep, na='NA', dec='.', row_names=True, col_names=True, qmethod='escape', append=False): """ Save the data into a .csv file. path : string with a path quote : quote character sep : separator character eol : end-of-line character(s) na : string for missing values dec : string for decimal separator row_names : boolean (save row names, or not) col_names : boolean (save column names, or not) comment_char : method to 'escape' special characters append : boolean (append if the file in the path is already existing, or not) """ path = conversion.py2rpy(path) append = conversion.py2rpy(append) sep = conversion.py2rpy(sep) eol = conversion.py2rpy(eol) na = conversion.py2rpy(na) dec = conversion.py2rpy(dec) row_names = conversion.py2rpy(row_names) col_names = conversion.py2rpy(col_names) qmethod = conversion.py2rpy(qmethod) res = self._write_table( self, **{'file': path, 'quote': quote, 'sep': sep, 'eol': eol, 'na': na, 'dec': dec, 'row.names': row_names, 'col.names': col_names, 'qmethod': qmethod, 'append': append}) return res def iter_row(self): """ iterator across rows """ for i in range(self.nrow): yield self.rx(i+1, rinterface.MissingArg) def iter_column(self): """ iterator across columns """ for i in range(self.ncol): yield self.rx(rinterface.MissingArg, i+1)
def test_mapperR2Python_s4(_set_class_AB): classname = rinterface.StrSexpVector(['A', ]) one = rinterface.IntSexpVector([1, ]) sexp = rinterface.globalenv['A'](x=one) assert isinstance(robjects.default_converter.rpy2py(sexp), robjects.RS4)
def testNACharacterInVector(self): na_str = ri.NACharacterType() x = ri.StrSexpVector(("ab", na_str, "cd")) self.assertTrue(x[1] is na_str) self.assertEqual("ab", x[0]) self.assertEqual("cd", x[2])
def test_init_from_seq_invalid_item(): seq = ['foo', 0, 'baz'] with pytest.raises(Exception): ri.StrSexpVector(seq)
def testGetItemLang(self): formula = ri.baseenv.get('formula') f = formula(ri.StrSexpVector(['y ~ x', ])) y = f[0] self.assertEqual(ri.SYMSXP, y.typeof)
def test_getitem(): vec = ri.StrSexpVector(['foo', 'bar', 'baz']) assert vec[1] == 'bar' with pytest.raises(TypeError): vec[(2, 3)]
def testGetSliceStr(self): vec = ri.StrSexpVector(['a','b','c']) vec = vec[0:2] self.assertEqual(2, len(vec)) self.assertEqual('a', vec[0]) self.assertEqual('b', vec[1])
def test_setitem(value): vec = ri.StrSexpVector(['foo', 'bar', 'baz']) vec[1] = value assert vec[1] == value with pytest.raises(TypeError): vec[(2, 3)] = value
def testIndexStr(self): x = ri.StrSexpVector(('a','b','c')) self.assertEqual(0, x.index('a')) self.assertEqual(2, x.index('c'))
def test_init(): rgetattr = ri.baseenv.find('::') formula = rgetattr('stats', 'formula') f = formula(ri.StrSexpVector(['y ~ x', ])) assert f.typeof == ri.RTYPES.LANGSXP