如何在Python中执行S4类方法(使用rpy2)?

2024-09-30 16:25:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我在R中创建了下面的S4类,它的构造函数接受一个名为“a”的变量,它是一个字符串。该类有一个名为“test_method”的方法,该方法将字符串“B”作为输入,并返回“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')
       }
    }
  )
)

现在,我可以创建这个类的一个实例并对其执行“test_method”:

object <- test_class(A='hello')
object$test_method('hi')

这将返回“否”,因为字符串不相等

现在我想保存我制作的这个对象,并从Python中执行“test_method”。我提出以下建议:

saveRDS(object, 'object.rds')

现在我知道了如何使用rpy2将这个对象读入Python(但是我并不真正关心使用哪个包,因为它可以工作):

from rpy2.robjects import R
r = R()
r_object = r.readRDS("object.rds")

但我现在如何执行“test_方法”?我试过这个,但不起作用:

r_object.test_method('hi')

这抛出:“AttributeError:'RS4'对象没有属性'test_method'”


Tags: 对象方法字符串testfieldsreturnobjecthi
1条回答
网友
1楼 · 发布于 2024-09-30 16:25:18

rpy2 documentation about S4 classes没有很好地覆盖引用类,这主要是因为rpy2代码早于S4的引用类扩展

简而言之,S4引用类没有映射到Python属性,但是编写一个子Python类这样做相对容易

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 TestClass(ro.methods.RS4): 
    def test_method(self, b): 
        return ro.baseenv['$'](self, 'test_method')(b) 

强制转换简单且计算成本低(父类的构造函数将只通过已经是S4对象的R对象):

s4testobj = TestClass(s4obj)

现在我们可以做:

>>> tuple(s4testobj.test_method('hi'))  
 ('no',)                                         

要在Python中从R类定义自动创建更多的方法和属性,并转换到自定义子级,您需要在Python端使用元编程,并定义自定义转换(在前面提供的文档链接中有到后者的链接)

注:如果没有绑定到S4参考类,R的R6类系统值得一看。该类系统的rpy2映射如下:https://github.com/rpy2/rpy2-R6

相关问题 更多 >