如何在 Python 中执行 S4 class 方法(使用 rpy2)?
How to execute S4 class method in Python (using rpy2)?
我在R中做了下面的S4 class,它的构造函数接受一个名为'A'的变量,它是一个字符串。 class 有一个名为 'test_method' 的方法,它将字符串 'B' 和 returns 作为输入,无论 'A' 是否等于 'B'.
test_class <- setRefClass(
"test_class",
fields=list(A="character"),
methods = list(
test_method = function(B) {
if (A==B) {
return('yes')
} else {
return('no')
}
}
)
)
现在,我可以创建此 class 的实例并在其上执行 'test_method':
object <- test_class(A='hello')
object$test_method('hi')
这个returns'no',因为字符串不相等
现在我想保存我制作的这个对象并从Python执行'test_method'。我做了一个 RDS:
saveRDS(object, 'object.rds')
现在我知道如何使用 rpy2 将此对象读入 Python(但是我真的不关心使用哪个包,因为它有效):
from rpy2.robjects import R
r = R()
r_object = r.readRDS("object.rds")
但是我现在如何执行'test_method'呢?我试过这个,但它不起作用:
r_object.test_method('hi')
这会抛出:“AttributeError:'RS4' 对象没有属性 'test_method'”
rpy2 documentation about S4 classes 没有很好地涵盖参考 classes,主要是因为 rpy2
代码早于参考 classes 对 S4 的扩展。
简而言之,S4 引用 classes 没有映射到 Python 属性,但是写一个子 Python class 是相对容易的。
import rpy2.robjects as ro
test_class = ro.r("""
setRefClass(
"test_class",
fields=list(A="character"),
methods = list(
test_method = function(B) {
if (A==B) {
return('yes')
} else {
return('no')
}
}
)
)
""")
s4obj = test_class(A='hello')
我们有一个相当通用的 S4 对象:
>>> type(s4obj)
rpy2.robjects.methods.RS4
编写一个继承自泛型 class 的子 class 可以如下所示:
class TestClass(ro.methods.RS4):
def test_method(self, b):
return ro.baseenv['$'](self, 'test_method')(b)
转换简单且计算成本低(父 class 的构造函数将只传递已经是 S4 对象的 R 对象):
s4testobj = TestClass(s4obj)
现在我们可以做:
>>> tuple(s4testobj.test_method('hi'))
('no',)
要从 R class 定义中自动创建 Python 中的方法和属性,并转换为自定义子项,您需要在 Python 上使用元编程侧,并定义自定义转换(在 link 之前提供的文档中有一个 link 到后者。
注意:如果不依赖于 S4 参考 类,R 的 R6 class 系统值得一看。 rpy2
对 class 系统的映射在这里:https://github.com/rpy2/rpy2-R6.
我在R中做了下面的S4 class,它的构造函数接受一个名为'A'的变量,它是一个字符串。 class 有一个名为 'test_method' 的方法,它将字符串 'B' 和 returns 作为输入,无论 'A' 是否等于 'B'.
test_class <- setRefClass(
"test_class",
fields=list(A="character"),
methods = list(
test_method = function(B) {
if (A==B) {
return('yes')
} else {
return('no')
}
}
)
)
现在,我可以创建此 class 的实例并在其上执行 'test_method':
object <- test_class(A='hello')
object$test_method('hi')
这个returns'no',因为字符串不相等
现在我想保存我制作的这个对象并从Python执行'test_method'。我做了一个 RDS:
saveRDS(object, 'object.rds')
现在我知道如何使用 rpy2 将此对象读入 Python(但是我真的不关心使用哪个包,因为它有效):
from rpy2.robjects import R
r = R()
r_object = r.readRDS("object.rds")
但是我现在如何执行'test_method'呢?我试过这个,但它不起作用:
r_object.test_method('hi')
这会抛出:“AttributeError:'RS4' 对象没有属性 'test_method'”
rpy2 documentation about S4 classes 没有很好地涵盖参考 classes,主要是因为 rpy2
代码早于参考 classes 对 S4 的扩展。
简而言之,S4 引用 classes 没有映射到 Python 属性,但是写一个子 Python class 是相对容易的。
import rpy2.robjects as ro
test_class = ro.r("""
setRefClass(
"test_class",
fields=list(A="character"),
methods = list(
test_method = function(B) {
if (A==B) {
return('yes')
} else {
return('no')
}
}
)
)
""")
s4obj = test_class(A='hello')
我们有一个相当通用的 S4 对象:
>>> type(s4obj)
rpy2.robjects.methods.RS4
编写一个继承自泛型 class 的子 class 可以如下所示:
class TestClass(ro.methods.RS4):
def test_method(self, b):
return ro.baseenv['$'](self, 'test_method')(b)
转换简单且计算成本低(父 class 的构造函数将只传递已经是 S4 对象的 R 对象):
s4testobj = TestClass(s4obj)
现在我们可以做:
>>> tuple(s4testobj.test_method('hi'))
('no',)
要从 R class 定义中自动创建 Python 中的方法和属性,并转换为自定义子项,您需要在 Python 上使用元编程侧,并定义自定义转换(在 link 之前提供的文档中有一个 link 到后者。
注意:如果不依赖于 S4 参考 类,R 的 R6 class 系统值得一看。 rpy2
对 class 系统的映射在这里:https://github.com/rpy2/rpy2-R6.