4

I am new to both R and rpy2. I am trying to port the following example

library(MASS)  # for eqscplot  
data(topo, package="MASS")  
topo.kr <- surf.ls(2, topo)  
trsurf <- trmat(topo.kr, 0, 6.5, 0, 6.5, 50)  

to rpy2.

So far I have

import  rpy2.robjects as robjects
robjects.r('library(spatial)')  
f1 = robjects.r['surf.ls']  
x = robjects.IntVector([1,2,3])  
y = robjects.IntVector([1,2,3])  
z = robjects.IntVector([1,30,3])  
res = f1(2, x,y,z)  

I assume that the result should be res. However when I print res using print(res.r_repr()) I get an expression which I am unable to evaluate. Would appreciate any help on this.

Kabira K
  • 1,916
  • 2
  • 22
  • 38
  • It is not clear to me what is "unable to evaluate"is. Also, your rpy2 code does not correspond to your R code (the call to surf.ls() does not have the same arguments). – lgautier Aug 12 '11 at 08:00
  • Also, why on earth are you loading both rpy and rpy2? It should be sufficient to `from rpy2 import robjects` and then use `robjects.r` and `robjects.IntVector` –  Aug 12 '11 at 13:03
  • By "unable to evaluate" means that when I issue "print res1.r_repr()" I don't get an array of values back. Instead res1 contains an r expression. My guess is that somehow to get the actual I need to issue a command to evaluate the expression. – Kabira K Aug 12 '11 at 19:10
  • I am not sure worried about the actual arguments as of now as much seen that function does something and returns a result. @Brandon: Thanks for pointing that i have fixed it. – Kabira K Aug 12 '11 at 19:12
  • @Sandeep: the side effect of calling print() is to have text printed to the console; I would have felt uneasy if it returned an array of values. The result of calling f1() is res1, and what you mean remains a mystery to me (beside calling print() or 'res' rather than 'res1'). – lgautier Aug 12 '11 at 20:54
  • There is some confusion here. surf.ls is a function that should return a vector of values. Currently I don't see that. I tried res() is an illegal operation (gives error that res is not callable). I think we can step back and ask the question as to how do we port the above R code in rpy2. – Kabira K Aug 12 '11 at 22:55

2 Answers2

2

Then the question is more: how do I convert an R list to a Python dictionary (little to do with evaluating expressions). With rpy2-2.2.x (and 2.3-dev):

from rpy2.robjects.vectors import ListVector
# make an R list
l = ListVector({'a': 1, 'b': 'b'})

# get a Python dict out of an R list
dict(l.iteritems())
lgautier
  • 11,363
  • 29
  • 42
  • it does work on my 2.1.9 install. Only trouble is that it does not convert the values (if they are IntVectors or FloatVectors) to python types. Something like dict([(i,[k for k in j]) for i, j in res.iteritems()]) unravels it, but that is getting thick. – Mark Aug 17 '11 at 01:35
  • @Mark: not only thick; it will only address one level of nesting. You could have a R list of R list of ... (you get the idea), and converting can probably be coded the shortest as a recursion. If your concern is only about the conversion of vectors of length 1 into Python scalars, that's only a matter of specifying it in the conversion rules (see http://rpy.sourceforge.net/rpy2/doc-2.2/html/robjects_convert.html#a-simple-example) – lgautier Aug 17 '11 at 11:00
1

Your code works fine. I think you are just having trouble accessing the results. Your resulting "res" object is essentially an R list. I would convert it into the corresponding Python dictionary.

rListObj = {}
for key,val in zip(robjects.r.names(res),res):
  rListObj[key] = [i for i in val] #R Vector to List

Results in:

{'f': [1.0, 1.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0], 'rx': [1, 3], 'ry': [1, 3], 'np': [2], 'beta': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 'r': [-1.7320508075688772, -1.6729239521451333e-16, -1.4142135623730951, -1.1547005383792512, -5.187907395343139e-17, -0.8164965809277259, -1.6729239521451333e-16, -1.4142135623730951, 3.415236843329339e-17, nan, -1.1547005383792512, -5.187907395343139e-17, -0.8164965809277259, nan, 0.0, -1.1547005383792512, -5.187907395343139e-17, -0.8164965809277259, nan, 0.0, 0.0], 'call': [<SignatureTranslatedFunction - Python:0xb7539dec / R:0xa686cec>, <IntVector - Python:0xb7534cac / R:0xa69e788>, <IntVector - Python:0xb7534d2c / R:0xa5f72f8>, <IntVector - Python:0xb7534c2c / R:0xa5f7320>, <IntVector - Python:0xb7534bac / R:0xa5f7348>], 'y': [1, 2, 3], 'x': [1, 2, 3], 'z': [1, 30, 3], 'wz': [0.0, 0.0, 0.0]}

I tested this against a somewhat old version of rpy2 (2.1.9), there are probably snazzier ways of doing this with more recent versions.

Mark
  • 106,305
  • 20
  • 172
  • 230