如何在 Python 中执行 S4 类方法(使用 rpy2)? [英] How to execute S4 class method in Python (using rpy2)?

查看:72
本文介绍了如何在 Python 中执行 S4 类方法(使用 rpy2)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 R 中创建了以下 S4 类,它的构造函数采用一个名为A"的变量,它是一个字符串.该类有一个名为test_method"的方法,它将字符串B"作为输入并返回A"是否等于B".

test_class <- setRefClass(测试类",字段=列表(A=字符"),方法=列表(test_method = 函数(B){如果(A==B){返回('是')} 别的 {返回('否')}}))

现在,我可以创建这个类的实例并在其上执行test_method":

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

这将返回 'no',因为字符串不相等.

现在我想保存我创建的这个对象并从 Python 执行test_method".我制作了一个 RDS:

saveRDS(object, 'object.rds')

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

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

但是我现在如何执行test_method"?我试过这个,但它不起作用:

r_object.test_method('hi')

这会抛出:AttributeError: 'RS4' object has no attribute 'test_method'"

解决方案

关于 S4 类的 rpy2 文档 没有很好地涵盖参考类,主要是因为 rpy2 代码早于 S4 的参考类扩展.

简而言之,S4 引用类没有映射到 Python 属性,但是编写一个子 Python 类来实现它相对容易.

import rpy2.robjects as rotest_class = ro.r(""";设置引用类(测试类",字段=列表(A=字符"),方法=列表(test_method = 函数(B){如果(A==B){返回('是')} 别的 {返回('否')}}))""")s4obj = test_class(A='你好')

我们有一个相当通用的 S4 对象:

<预><代码>>>>类型(s4obj)rpy2.robjects.methods.RS4

编写一个继承自该泛型类的子类可以如下所示:

class TestClass(ro.methods.RS4):def test_method(self, b):返回 ro.baseenv['$'](self, 'test_method')(b)

转换很简单,计算成本也很低(父类的构造函数只会传递一个已经是 S4 对象的 R 对象):

s4testobj = TestClass(s4obj)

现在我们可以:

<预><代码>>>>元组(s4testobj.test_method('嗨'))('不',)

对于从 R 类定义中额外自动创建 Python 中的方法和属性,并转换为自定义子项,您需要在 Python 端使用元编程,并定义自定义转换(有指向后者的链接在前面提供的文档的链接中).

注意:如果不绑定到 S4 参考类,R 的 R6 类系统值得一看.该类系统的 rpy2 映射在这里:https://github.com/rpy2/rpy2-R6.

I have made the following S4 class in R, its constructor takes a variable called 'A', which is a string. The class has a method called 'test_method', which takes as input a string 'B' and returns whether 'A' equals 'B'.

test_class <- setRefClass(
  "test_class",
  fields=list(A="character"),
  methods = list(
    test_method = function(B) {
       if (A==B) {
           return('yes')
       } else {
           return('no')
       }
    }
  )
)

Now, I can make an instance of this class and execute 'test_method' on it:

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

This returns 'no', because the strings do not equal.

Now I want to save this object I have made and execute 'test_method' from Python. I make an RDS:

saveRDS(object, 'object.rds')

Now I know how to read this object into Python using rpy2 (however I don't really care which package to use, as it works):

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

But how can I execute 'test_method' now? I tried this, but it doesn't work:

r_object.test_method('hi')

This throws: "AttributeError: 'RS4' object has no attribute 'test_method'"

解决方案

The rpy2 documentation about S4 classes does not cover well reference classes mostly because the rpy2 code predates the reference classes extension to S4.

In short, the S4 reference classes are not mapped to Python attributes, but writing a child Python class that does it is relatively easy.

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')

We have a rather generic S4 object:

>>> type(s4obj)
rpy2.robjects.methods.RS4

Writing a child class that inherits from that generic class can look like this:

class TestClass(ro.methods.RS4): 
    def test_method(self, b): 
        return ro.baseenv['$'](self, 'test_method')(b) 

Casting is straightforward and computationally cheap (the parent class's constructor will just pass through an R object that is already an S4 object):

s4testobj = TestClass(s4obj)

Now we can do:

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

For additional automagical creation of methods and attributes in Python from the R class definition, and conversion to the custom child, you'll need to use metaprogramming on the Python side, and define custom conversion (there is a link to the latter in the link to the documentation provided earlier).

Note: If not tied to S4 Reference Classes, the R6 class system for R is worth a look. An rpy2's mapping for that class system is here: https://github.com/rpy2/rpy2-R6.

这篇关于如何在 Python 中执行 S4 类方法(使用 rpy2)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆