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

时间:2017-07-27 19:27:37

标签: python numpy rpy2

SO上有很多相关的答案,但所有这些答案都使用rpy2提供的高级robjects界面。但是,如果我想使用低级接口,我该怎么做呢?以下是MCVE(如果您在R中安装了package copula):

备选方案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')

1 个答案:

答案 0 :(得分:1)

感谢您对高级界面及其所涉及的工作的赞赏,尽管这是一个含蓄的界面:它确实旨在“正常工作”。

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

我建议您使用高级接口,除非有特殊原因,但由于源打开,转换器中发生的事情可以轻松检查(here)。