我无法使以下代码生效,但我没有看到此错误在R中严格运作。
from rpy2.robjects.packages import importr
from rpy2 import robjects
import numpy as np
forecast = importr('forecast')
ts = robjects.r['ts']
y = np.random.randn(50)
X = np.random.randn(50)
y = ts(robjects.FloatVector(y), start=robjects.IntVector((2004, 1)), frequency=12)
X = ts(robjects.FloatVector(X), start=robjects.IntVector((2004, 1)), frequency=12)
forecast.Arima(y, xreg=X, order=robjects.IntVector((1, 0, 0)))
考虑到以下代码工作正常,这一点特别令人困惑
forecast.auto_arima(y, xreg=X)
无论我为X使用什么,使用numpy接口,我都会看到以下回溯。有什么想法吗?
---------------------------------------------------------------------------
RRuntimeError Traceback (most recent call last)
<ipython-input-20-b781220efb93> in <module>()
13 X = ts(robjects.FloatVector(X), start=robjects.IntVector((2004, 1)), frequency=12)
14
---> 15 forecast.Arima(y, xreg=X, order=robjects.IntVector((1, 0, 0)))
/home/skipper/.local/lib/python2.7/site-packages/rpy2/robjects/functions.pyc in __call__(self, *args, **kwargs)
84 v = kwargs.pop(k)
85 kwargs[r_k] = v
---> 86 return super(SignatureTranslatedFunction, self).__call__(*args, **kwargs)
/home/skipper/.local/lib/python2.7/site-packages/rpy2/robjects/functions.pyc in __call__(self, *args, **kwargs)
33 for k, v in kwargs.iteritems():
34 new_kwargs[k] = conversion.py2ri(v)
---> 35 res = super(Function, self).__call__(*new_args, **new_kwargs)
36 res = conversion.ri2py(res)
37 return res
RRuntimeError: Error in `colnames<-`(`*tmp*`, value = if (ncol(xreg) == 1) nmxreg else paste(nmxreg, :
length of 'dimnames' [2] not equal to array extent
修改:
问题是以下代码行不会计算为列名,这似乎是R方的期望。
sub = robjects.r['substitute']
deparse = robjects.r['deparse']
deparse(sub(X))
我不太清楚R代码对此代码的期望是什么,但我无法通过返回length == 1
的内容找到通过此检查的RPy2对象。这对我来说真的像个错误。
R> length(deparse(substitute((rep(.2, 1000)))))
[1] 1
但是在Rpy2中
[~/]
[94]: robjects.r.length(robjects.r.deparse(robjects.r.substitute(robjects.r('rep(.2, 1000)'))))
[94]:
<IntVector - Python:0x7ce1560 / R:0x80adc28>
[ 78]
答案 0 :(得分:2)
这是相同基础问题的一种表现形式(例如,见other related issue):R表达式被懒惰地评估并且可以在R中被操纵,这导致不能很好地转换的习语(在Python表达式中是立即评估,并且必须移动到AST来操纵代码。)
问题第二部分的答案。在R中,substitute(rep(.2, 1000))
将未评估的表达式rep(.2, 1000)
传递给substitute()
。在rpy2
substitute('rep(.2, 1000)')`
传递一个字符串; R等价物是
substitute("rep(.2, 1000)")
以下是让您接近R&#39 {s} deparse(substitute())
:
from rpy2.robjects.packages import importr
base = importr('base')
from rpy2 import rinterface
# expression
e = rinterface.parse('rep(.2, 1000)')
dse = base.deparse(base.substitute(e))
>>> len(dse)
1
>>> print(dse) # not identical to R
"expression(rep(0.2, 1000))"
目前,解决此问题的一种方法是将R对象绑定到R符号 (最好是在专用环境而不是GlobalEnv中),并使用 R调用中的符号写成字符串:
from rpy2.robjects import Environment, reval
env = Environment()
for k,v in (('y', y), ('xreg', X), ('order', robjects.IntVector((1, 0, 0)))):
env[k] = v
# make an expression
expr = rinterface.parse("forecast.Arima(y, xreg=X, order=order)")
# evaluate in the environment
res = reval(expr, envir=env)
这不是我作为解决方案而感到高兴的事情,但我从未找到时间来研究更好的解决方案。
编辑:使用rpy2-2.4.0,可以使用R符号并执行以下操作:
RSymbol = robjects.rinterface.SexpSymbol
pairlist = (('x', RSymbol('y')),
('xreg', RSymbol('xreg')),
('order', RSymbol('order')))
res = forecast.Arima.rcall(pairlist,
env)
这还不是最直观的界面。使用上下文管理器可能会更好。
答案 1 :(得分:0)
有一种方法可以简单地将变量传递给R而不替换,并将结果返回给python。您可以在https://stackoverflow.com/a/55900840/5350311中找到一个简单的示例。我想更清楚地知道将传递给R的内容以及返回的内容,特别是在使用For循环和大量变量的情况下。