Revision: 564 http://rpy.svn.sourceforge.net/rpy/?rev=564&view=rev Author: lgautier Date: 2008-06-25 13:50:25 -0700 (Wed, 25 Jun 2008)
Log Message: ----------- Long-due commit. setup: o package name is now ryp2 (no longer rpython) o version bumped to 1.0a1 (might change to 2.0a1, as version number can be confusing - rpy has 1.0.x) doc: o fixes and additions rinterface: o cut dead code o default environment for do_eval_expr is now R_GlobalEnv o restore evaluation of R functions in their CLOENV robjects: o class Formula o aliases for (Str|Int|Float)SexpVector classes in rinterface Modified Paths: -------------- branches/rpy_nextgen/demos/radmin.py branches/rpy_nextgen/doc/source/conf.py branches/rpy_nextgen/doc/source/overview.rst branches/rpy_nextgen/doc/source/rinterface.rst branches/rpy_nextgen/doc/source/robjects.rst branches/rpy_nextgen/rpy/rinterface/__init__.py branches/rpy_nextgen/rpy/rinterface/rinterface.c branches/rpy_nextgen/rpy/robjects/__init__.py branches/rpy_nextgen/rpy/robjects/tests/__init__.py branches/rpy_nextgen/setup.py Modified: branches/rpy_nextgen/demos/radmin.py =================================================================== --- branches/rpy_nextgen/demos/radmin.py 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/demos/radmin.py 2008-06-25 20:50:25 UTC (rev 564) @@ -1,5 +1,6 @@ """ -A front-end to R's packags, and help/documentation systems +An R frontend + """ import os, sys Modified: branches/rpy_nextgen/doc/source/conf.py =================================================================== --- branches/rpy_nextgen/doc/source/conf.py 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/doc/source/conf.py 2008-06-25 20:50:25 UTC (rev 564) @@ -44,7 +44,7 @@ # The short X.Y version. version = '1.0' # The full version, including alpha/beta/rc tags. -release = '1.0a0' +release = '1.0a1' # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: Modified: branches/rpy_nextgen/doc/source/overview.rst =================================================================== --- branches/rpy_nextgen/doc/source/overview.rst 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/doc/source/overview.rst 2008-06-25 20:50:25 UTC (rev 564) @@ -54,7 +54,7 @@ ^^^^^^^^^^^^^^^^^^^^^^ Low-level interface to R, when speed and flexibility -matter most. Here the programmer gets close(r) to R's C +matter most. Here the programmer gets close(r) to R's C-level API. @@ -71,8 +71,11 @@ and :mod:`rpy2.robjects`: an :class:`rpy2.rinterface.SexpClosure` can be given any :class:`rpy2.robjects.RObject` as a parameter while any :class:`rpy2.robjects.RFunction` can be given any -:class:`rpy2.rinterface.Sexp`. +:class:`rpy2.rinterface.Sexp`. Choosing inheritance does not only +come with advantages: `setters` on `R` objects would be more intuitive +with a container/delegation approach. The module :mod:`rpy2.rpy_classic` is using delegation, letting us demonstrate how to extend :mod:`rpy2.rinterface` with an alternative -to inheritance. \ No newline at end of file +to inheritance. + Modified: branches/rpy_nextgen/doc/source/rinterface.rst =================================================================== --- branches/rpy_nextgen/doc/source/rinterface.rst 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/doc/source/rinterface.rst 2008-06-25 20:50:25 UTC (rev 564) @@ -46,8 +46,8 @@ .. note:: If calling :func:`initEmbeddedR` returns an error stating that - `R_HOME` is defined, you should either have the R executable in - your path ($PATH on unix-alikes, %Path% on Microsoft Windows) or + `R_HOME` is not defined, you should either have the R executable in + your path (`$PATH` on unix-alikes, `%Path%` on Microsoft Windows) or have the environment variable `R_HOME` defined. R space and Python space @@ -86,8 +86,8 @@ The base package has a namespace, that can be accessed as an environment. .. note:: - Depending on what is in globalEnv and on the attached packages, base - objects can be masked when starting the search from globalEnv. Use this + Depending on what is in `globalEnv` and on the attached packages, base + objects can be masked when starting the search from `globalEnv`. Use this environment when you want to be sure to access a function you know to be in the base namespace. Modified: branches/rpy_nextgen/doc/source/robjects.rst =================================================================== --- branches/rpy_nextgen/doc/source/robjects.rst 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/doc/source/robjects.rst 2008-06-25 20:50:25 UTC (rev 564) @@ -1,4 +1,4 @@ -.. index:: +. index:: module: rpy2.robjects @@ -274,14 +274,65 @@ The class inherits from the class :class:`rpy2.rinterface.SexpClosure`. +.. index:: + pair: robjects; RFormula + single: formula +Formulae +======== + +For tasks such as modelling and plotting, an R formula can be +a terse, yet readable, way of expressing what is wanted. + +In R, it generally looks like: + +.. code-block:: r + + x <- 1:10 + y <- x + rnorm(10, sd=0.2) + + fit <- lm(y ~ x) + +In the call to `lm`, the argument is a `formula`. +A formula is a `R` language object, and the terms in the formula +are evaluated in the environment it was defined in. Without further +specification, that environment is the environment in which the +the formula is created. + +The class :class:`robjects.RFormula` is representing an `R` formula, +and represents a convenient way of specifying your code. + +.. code-block:: python + + x = robjects.RVector(array.array('i', range(1, 11))) + y = x + robjects.r.rnorm(10, sd=0.2) + + fmla = robjects.RFormula('y ~ x') + env = fmla.getenvironment() + env['x'] = x + env['y'] = y + + fit = robjects.r.lm(fmla) + +One drawback with that approach is that pretty printing of +the `fit` object is note quite as clear as what one would +expect when working in `R`. +However, by evaluating R code on +the fly, we can obtain a `fit` object that will display +nicely: + +.. code-block:: python + + fit = robjects.r('lm(%s)' %fmla.__repr__()) + + Mapping between rpy2 objects and other python objects ===================================================== -The mapping between low-level objects is performed by the -functions XXX and XXX. +The mapping between low-level objects is performed on +the fly by functions XXX -A developper can easily add his own mapping XXX. +Those functions can be modifyied to satisfy all requirements. Examples Modified: branches/rpy_nextgen/rpy/rinterface/__init__.py =================================================================== --- branches/rpy_nextgen/rpy/rinterface/__init__.py 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/rpy/rinterface/__init__.py 2008-06-25 20:50:25 UTC (rev 564) @@ -35,3 +35,19 @@ from rpy2.rinterface.rinterface import * + + +class StrSexpVector(SexpVector): + def __init__(self, v): + super(StrSexpVector, self).__init__(v, STRSXP) + + +class IntSexpVector(SexpVector): + def __init__(self, v): + super(StrSexpVector, self).__init__(v, INTSXP) + + +class FloatSexpVector(SexpVector): + def __init__(self, v): + super(StrSexpVector, self).__init__(v, REALSXP) + Modified: branches/rpy_nextgen/rpy/rinterface/rinterface.c =================================================================== --- branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/rpy/rinterface/rinterface.c 2008-06-25 20:50:25 UTC (rev 564) @@ -592,24 +592,8 @@ }; -/* static PyObject* */ -/* Sexp_new(PyTypeObject *type, PyObject *args) */ -/* { */ -/* PyObject object, res; */ -/* if (!PyArg_ParseTuple(args, "O:new", */ -/* &object)) */ -/* PyErr_Format(PyExc_ValueError, "Can only instanciate from PySexpObject"); */ -/* return NULL; */ -/* res = (PySexpObject *)_PyObject_New(&Sexp_Type); */ -/* if (!res) */ -/* PyErr_NoMemory(); */ -/* res->sexp = sexp; */ -/* return res; */ -/* } */ - - /* * Closure-type Sexp. */ @@ -624,8 +608,11 @@ //FIXME: if env_R is null, use R_BaseEnv + //shouldn't it be R_GlobalContext (but then it throws a NULL error) ? if (isNull(env_R)) { - env_R = R_BaseEnv; + //env_R = R_BaseEnv; + env_R = R_GlobalEnv; + //env_R = R_GlobalContext; } /* Enable our handler for SIGINT inside the R @@ -771,8 +758,8 @@ } //FIXME: R_GlobalContext ? - PROTECT(res_R = do_eval_expr(call_R, R_GlobalEnv)); - //PROTECT(res_R = do_eval_expr(call_R, CLOENV(fun_R))); + //PROTECT(res_R = do_eval_expr(call_R, R_GlobalEnv)); + PROTECT(res_R = do_eval_expr(call_R, CLOENV(fun_R))); /* if (!res) { */ /* UNPROTECT(2); */ Modified: branches/rpy_nextgen/rpy/robjects/__init__.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/__init__.py 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/rpy/robjects/__init__.py 2008-06-25 20:50:25 UTC (rev 564) @@ -10,7 +10,11 @@ import array import rpy2.rinterface as rinterface +StrSexpVector = rinterface.StrSexpVector +IntSexpVector = rinterface.IntSexpVector +FloatSexpVector = rinterface.FloatSexpVector + #FIXME: close everything when leaving (check RPy for that). def default_ri2py(o): @@ -28,6 +32,8 @@ res = REnvironment(o) elif isinstance(o, rinterface.SexpS4): res = RS4(o) + elif rinterface.baseNameSpaceEnv['class'](o)[0] == 'formula': + res = RFormula(o) else: res = RObject(o) return res @@ -290,13 +296,34 @@ res = ri2py(res) return res + class RS4(RObjectMixin, rinterface.SexpS4): def __getattr__(self, attr): res = self.do_slot(attr) return res + +class RFormula(RObjectMixin, rinterface.Sexp): + + def __init__(self, formula, environment = rinterface.globalEnv): + inpackage = rinterface.baseNameSpaceEnv["::"] + asformula = inpackage(StrSexpVector(['stats', ]), + StrSexpVector(['as.formula', ])) + robj = asformula(rinterface.SexpVector(StrSexpVector([formula, ])), + env = environment) + super(RFormula, self).__init__(robj) + + def getenvironment(self): + """ Return the R environment in which the formula will look for + its variables. """ + res = self.do_slot(".Environment") + res = ri2py(res) + return res + + + class R(object): _instance = None Modified: branches/rpy_nextgen/rpy/robjects/tests/__init__.py =================================================================== --- branches/rpy_nextgen/rpy/robjects/tests/__init__.py 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/rpy/robjects/tests/__init__.py 2008-06-25 20:50:25 UTC (rev 564) @@ -3,6 +3,7 @@ import testRObject import testRVector import testRArray +import testRFormula import testRFunction import testREnvironment import testRobjects @@ -13,12 +14,14 @@ suite_RArray = testRArray.suite() suite_RFunction = testRFunction.suite() suite_REnvironment = testREnvironment.suite() + suite_RFormula = testRFormula.suite() suite_Robjects = testRobjects.suite() alltests = unittest.TestSuite([suite_RObject, suite_RVector, suite_RArray, suite_RFunction, suite_REnvironment, + suite_RFormula, suite_Robjects ]) return alltests Modified: branches/rpy_nextgen/setup.py =================================================================== --- branches/rpy_nextgen/setup.py 2008-06-15 22:10:56 UTC (rev 563) +++ branches/rpy_nextgen/setup.py 2008-06-25 20:50:25 UTC (rev 564) @@ -2,17 +2,9 @@ import os, os.path, sys, shutil, re, itertools from distutils.core import setup, Extension -#FIXME: still needed ? -try: - import ctypes -except Exception, e: - print(e) - print("A working 'ctypes' module is required.") - sys.exit(1) - pack_name = 'rpy2' -pack_version = '1.0-a0' +pack_version = '1.0-a1' RHOMES = os.getenv('RHOMES') @@ -133,7 +125,7 @@ pack_dir = {pack_name: 'rpy'} -setup(name = "rpython", +setup(name = pack_name, version = pack_version, description = "Python interface to the R language", url = "http://rpy.sourceforge.net", @@ -141,6 +133,8 @@ ext_modules = rinterface_exts, package_dir = pack_dir, packages = [pack_name, + pack_name+'.rlike', + pack_name+'.rlike.tests', pack_name+'.robjects', pack_name+'.robjects.tests'] + \ [pack_name + '.rinterface', pack_name + '.rinterface.tests'] This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ rpy-list mailing list rpy-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rpy-list