使用rpy2 eval表达式的指导

4

我是R和rpy2的新手。我正在尝试移植以下示例:

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)  

关于rpy2。

到目前为止,我已经

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)  

我认为结果应该是res。然而,当我使用print(res.r_repr())打印res时,得到的是一个无法评估的表达式。希望能得到帮助。

我不清楚"unable to evaluate"是什么意思。此外,您的rpy2代码与R代码不对应(surf.ls()的调用参数不同)。 - lgautier
另外,你为什么要同时加载rpy和rpy2?只需要使用from rpy2 import robjects,然后使用robjects.rrobjects.IntVector即可。 - user626998
“无法评估”意味着当我发出“print res1.r_repr()”时,我没有得到一个值数组。相反,res1包含一个r表达式。我的猜测是,需要发出一个命令来评估表达式以获取实际值。 - Kabira K
我现在并不担心实际参数,因为我更关注函数是否执行了某些操作并返回了结果。@Brandon:感谢您指出这一点,我已经修复了它。 - Kabira K
@Sandeep:调用print()的副作用是将文本打印到控制台;如果它返回一个值数组,我会感到不安。调用f1()的结果是res1,你的意思对我来说仍然是个谜(除了调用print()或'res'而不是'res1')。 - lgautier
这里有一些混淆。surf.ls是一个应该返回值向量的函数。目前我没有看到那个。我尝试过res(),但这是非法操作(会出现错误,指出res不可调用)。我认为我们可以退后一步,问一下如何在rpy2中移植上述R代码。 - Kabira K
2个回答

2

那么问题更多了:我如何将R列表转换为Python字典(与表达式求值几乎无关)。 使用rpy2-2.2.x(和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())

它在我的2.1.9安装上可以工作。唯一的问题是,如果它们是IntVectors或FloatVectors,它不会将值转换为Python类型。类似dict([(i,[k for k in j]) for i,j in res.iteritems()])的东西可以解开它,但那太复杂了。 - Mark
@Mark:不仅仅是厚度的问题;它只能处理一层嵌套。你可以有一个R列表,其中包含R列表...(你懂的),并且转换可能最短的编码方式可能是递归。如果您关心的只是将长度为1的向量转换为Python标量,那只需要在转换规则中指定即可(请参见http://rpy.sourceforge.net/rpy2/doc-2.2/html/robjects_convert.html#a-simple-example)。 - lgautier

1

你的代码运行得很好。我认为你只是在访问结果方面遇到了一些困难。你的“res”对象实质上是一个R列表。我建议将其转换为相应的Python字典。

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

结果为:

{'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]}

我对一个相对较旧的rpy2版本(2.1.9)进行了测试,可能有更时髦的方法可以在更新的版本中实现。


谢谢Mark。这就是我所缺少的。 - Kabira K
@Mark:有更简单的方法可以做到这一点(已在2.2.x和2.3-dev上测试;它/可能/适用于2.1.x系列)。请参见下文。 - lgautier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接