2014-04-20 48 views
2

我無法做出下面的代碼的工作,雖然我沒有看到這個錯誤R.嚴格工作從rpy2傳遞給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對象。這對我來說看起來像一個bug。

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] 
+4

任何人都在意詳細說明爲什麼這個問題是downvoted? – jseabold

+0

我想補充一點,這似乎是一個合理的問題,揭示可能是一個普遍問題。獲得這個特定的示例工作可能會幫助其他人。這就是說,我不知道這個問題很容易解決。 –

+0

@jseabold:我不明白爲什麼人們會開車下樓。我認爲,無法解釋的投票可能會被明顯忽略。 – lgautier

回答

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

這還不是最直觀的界面。可能是使用上下文管理器的東西會更好。

+0

感謝這對於究竟發生了什麼,但是它並沒有清楚(對我來說)我可以通過的那個對象將在R方面通過這個'deparse(substitute(X))',如R所期望的那樣。我在R端修補了代碼,但對於這個特殊情況來說這是一個破解。我想知道在這種情況下R代碼本身是不是最理想的,但我不知道R足夠好說。 – jseabold

+0

我添加了一個解決方案的胚胎。 – lgautier