如何在rpy2中使用R&C的赋值方法?

时间:2016-08-06 17:23:06

标签: python r rpy2

我正在使用rpy2,我需要在R对象上使用赋值方法。例如,从这个对象开始:

npm start

假设我要分配给# Python code from rpy2.robjects import r myvar = r('c(a=1,b=2,c=3)') 。 (注意:忽略rpy2提供了另一种通过names(myvar)访问名称的方式。这只适用于名称,而不是任意赋值方法。)在R中,我会这样做:

myvar.names

然而,这在Python中不起作用:

# R code
names(myvar) <- c("x", "y", "z")

当然,我可以通过rpy2&#39的字符串eval运行任意代码:

# Python code
> names(myvar) = ['x', 'y', 'z']
In [62]: names(myvar) = ['x', 'y', 'z']
  File "<ipython-input-62-aa3f7998cdcb>", line 1
    names(myvar) = ['x', 'y', 'z']
                                  ^
SyntaxError: can't assign to function call

但是将值插值到要评估的字符串中听起来并不有趣或安全。那么有没有办法安全地通过rpy2安全地做# Python code r('''names(myvar) <- c("x", "y", "z")''')

2 个答案:

答案 0 :(得分:3)

在R中,“setter”函数遵循命名约定,该命名约定使“getter”的名称后跟<-。例如,在做

names(myvar) <- c("x", "y", "z")

发生以下情况:

myvar <- "names<-"(myvar, c("x","y","z"))

如果我们将其分解:

> myvar = c(a=1,b=2,c=3)
> # call the assignment function "names<-"    
> "names<-"(myvar, c("x","y","z")) 
x y z 
1 2 3 
> # the "names" are stored as an attribute
> attributes(myvar)
$names
[1] "x" "y" "z"
> attributes(myvar)$names <- c("a","b","c")
> myvar
a b c 
1 2 3 
> # note that the function does have a side effect
> # (unlike what I wrote in a previous version of this answer):
> # the names are changed in place. I think that this is a C-level
> # optimization specific to "names" and this may not always be
> # the case for all "setters"
> "names<-"(myvar, c("x","y","z")) 
x y z 
1 2 3 
> myvar
x y z 
1 2 3   

从rpy2做一些类似method(object) <- value的事情非常简单。 python代码看起来像:

set_method = r("`method<-`")
my_object = set_method(my_object, value)

答案 1 :(得分:1)

考虑导入R&lt; 1&gt;基础包并直接使用c()函数并指定名称导入R&lt; stats包并直接使用setNames()函数。下面显示了如何使用r()base.c()分配产生等效值:

from rpy2.robjects import r
from rpy2.robjects.packages import importr

base = importr('base')

myvar1 = r("c('x','y','z')")
myvar2 = base.c('x', 'y', 'z')

# SAME CLASS TYPE
print(type(myvar1))
# <class 'rpy2.robjects.vectors.StrVector'>
print(type(myvar2))
# <class 'rpy2.robjects.vectors.StrVector'>

from rpy2.robjects import pandas2ri
pandas2ri.activate()

# CONVERT TO PYTHON NUMPY ARRAY
py_myvar1 = pandas2ri.ri2py(myvar1)
py_myvar2 = pandas2ri.ri2py(myvar2)

print(py_myvar1==py_myvar2)
# [ True  True  True]

print(py_myvar1)
# ['x' 'y' 'z']
print(py_myvar2)
# ['x' 'y' 'z']

使用名称和值的输出向量分配名称:

stats = importr('stats')
# EQUIVALENT TO R: myvar <- setNames(c('a', 'b', 'c'), c(1,2,3))
myvar3 = stats.setNames(base.c(1,2,3), base.c('a', 'b', 'c'))

print(type(myvar3))
# <class 'rpy2.robjects.vectors.IntVector'>

# NAME VECTOR
py_myvar3 = pandas2ri.ri2py(base.names(myvar3))
print(py_myvar3)
# ['a' 'b' 'c']

# VALUES VECTOR
py_myvar3 = pandas2ri.ri2py(myvar3)
print(py_myvar3)
# [1 2 3]

总而言之,Python不允许为函数调用赋值。因此,找到适当的方法来创建一个对象,并为它指定右侧的值,使其符合Python的惯例。