在rpy2> = 3.0.0中,有没有办法从R向量,矩阵等返回名称

时间:2019-03-01 19:59:50

标签: python-3.x rpy2

我想从命名的R向量(或矩阵等)中获取名称,再返回到Python中。在rpy2 <3.0.0中,这是可能的,例如

>>> stats.quantile(numpy.array([1,2,3,4]))
R object with classes: ('numeric',) mapped to:
<FloatVector - Python:0x7f3e664d6d88 / R:0x55c939a540c8>
[1.000000, 1.750000, 2.500000, 3.250000, 4.000000]
>>> stats.quantile(numpy.array([1,2,3,4])).names
R object with classes: ('character',) mapped to:
<StrVector - Python:0x7f3e66510788 / R:0x55c939a53648>
['0%', '25%', '50%', '75%', '100%']
>>> stats.quantile(numpy.array([1,2,3,4])).rx('25%')
R object with classes: ('numeric',) mapped to:
<FloatVector - Python:0x7f3e68770bc8 / R:0x55c938f23ba8>
[1.750000]

但是在rpy2> = 3.0.0中,输出将转换为numpy数组,因此当然没有.names或.rx,因此名称似乎丢失了。

>>> stats.quantile(numpy.array([1,2,3,4]))
array([1.  , 1.75, 2.5 , 3.25, 4.  ])

1 个答案:

答案 0 :(得分:1)

rpy2 3.0.0试图简化其转换系统,从而使其缺陷更容易预期和缓解。

在这里,当numpy转换层处于活动状态时,会发生以下情况:

  • 只要R需要,numpy数组就会转换为R数组
  • 从R返回时,R数组将转换为numpy数组

这种对称性不是必须的,而仅仅是默认numpy转换层的方式。可以设置一个非对称转换层,这里将把numpy数组转换为R数组,但是当从R返回时,将R数组原样保留为相对较快和容易。

import numpy
from rpy2.rinterface_lib import sexp
from rpy2 import robjects
from rpy2.robjects import conversion
from rpy2.robjects import numpy2ri

# We are going to build our custom converter by subtraction, that is
# starting from the numpy converter and only revert the part converting R
# objects into numpy arrays to the default conversion. We could have also
# build it by addition. 
myconverter = conversion.Converter('assym. numpy',
                                   template=numpy2ri.converter)
myconverter.rpy2py.register(sexp.Sexp,
                            robjects.default_converter.rpy2py)

然后可以在需要时使用该自定义转换:

with conversion.localconverter(myconverter):
    res = stats.quantile(numpy.array([1, 2, 3, 4]))

结果是:

>>> print(res.names)                                                                                                   
[1] "0%"   "25%"  "50%"  "75%"  "100%"

如果这看起来太费力,您也可以完全跳过numpy转换器,仅使用默认转换器,并在需要时手动将numpy数组强制转换为合适的R数组:

>>> stats.quantile(robjects.vectors.IntVector(numpy.array([1, 2, 3, 4]))).names                                           
R object with classes: ('character',) mapped to:
['0%', '25%', '50%', '75%', '100%']