使用 rpy2 低级接口将 numpy 转换为 R 数组

Converting numpy to R array using rpy2 low level interface

SO上有很多相关的回答,但是都是用R中安装的rpy2. But, if I wanted to use the low-level interface, how do I go about it? Following is a MCVE (provided you have the package copula提供的高级robjects接口:

备选方案 1,仅使用 the docs

中的低级接口
import numpy as np
from rpy2 import rinterface as ri

ri.initr()

def rimport(packname):
    as_environment = ri.baseenv['as.environment']
    require = ri.baseenv['require']
    require(ri.StrSexpVector([packname]),
            quiet = ri.BoolSexpVector((True, )))
    packname = ri.StrSexpVector(['package:' + str(packname)])
    pack_env = as_environment(packname)
    return pack_env

Copula = rimport('copula')

# The ri.SexpVector line causes the problem, but this is how the docs has it.
gc = Copula['gofCopula'](copula=Copula['gumbelCopula'](dim=5),
                         x=ri.SexpVector(np.random.randn(100,5), ri.REALSXP),
                         N=ri.IntSexpVector((1000,)),
                         simulation=ri.StrSexpVector(('mult',)))
死于:
RRuntimeError                             Traceback (most recent call last)
<ipython-input-3-63487c32d528> in <module>()
      2                          x=ri.SexpVector(np.random.randn(100,5), ri.REALSXP),
      3                          N=ri.IntSexpVector((1000,)),
----> 4                          simulation=ri.StrSexpVector(('mult',)))
      5 
      6 gc

RRuntimeError: Error: (d <- ncol(x)) > 1 is not TRUE

备选方案 2,使用 numpy2ri,如 SO

上的所有答案所示
import numpy as np
from rpy2 import rinterface as ri
from rpy2.robjects import numpy2ri

ri.initr()
numpy2ri.activate()

def rimport(packname):
    as_environment = ri.baseenv['as.environment']
    require = ri.baseenv['require']
    require(ri.StrSexpVector([packname]),
            quiet = ri.BoolSexpVector((True, )))
    packname = ri.StrSexpVector(['package:' + str(packname)])
    pack_env = as_environment(packname)
    return pack_env

Copula = rimport('copula')

# Automatic conversion does not happen!
gc = Copula['gofCopula'](copula=Copula['gumbelCopula'](dim=5),
                         x=np.random.randn(100,5), # Hoping for automatic conversion
                         N=ri.IntSexpVector((1000,)),
                         simulation=ri.StrSexpVector(('mult',)))
死于:
ValueError                                Traceback (most recent call last)
<ipython-input-1-17b2b5105f01> in <module>()
     24                          x=np.random.randn(100,5),
     25                          N=ri.IntSexpVector((1000,)),
---> 26                          simulation=ri.StrSexpVector(('mult',)))
     27 
     28 gc

ValueError: All parameters must be of type Sexp_Type,or Python int/long, float, bool, or None

备选方案 3,同时使用两者

像备选方案 1 一样死去。


补充说明

1)

list(ri.SexpVector(np.random.randn(100,5), ri.REALSXP))

是一个包含 NA_real_ 的列表,正好是其中的 100 个。

2)

如果我放弃低级接口,只使用高级接口,一切正常。但这不是我要找的。

import numpy as np
from rpy2.robjects.packages import importr
from rpy2.robjects import numpy2ri

numpy2ri.activate()

Copula = importr('copula')
gc = Copula.gofCopula(copula=partial(Copula.gumbelCopula, dim=5)(),
                      x=np.random.randn(100,5),
                      N=1000,
                      simulation='mult')

感谢您对高级界面及其相关工作的称赞,虽然这是一个隐含的界面:它确实旨在 "just work"。

低级接口与 R 的 C 级接口非常接近 API,它的使用可能需要更多关于它的知识,这被认为是 Python 观众的合理期望。请注意,很遗憾,发布的文档并不完整,因为未包含文档字符串 (issue with readthedocs)。

除非有特殊原因,否则我鼓励您使用高级界面,但由于源代码是开放的,因此可以轻松检查转换器中发生的事情(here)。