Repository: statsmodels/statsmodels

Issue:
Some issues with ARMAX forecasting
Not reported but evident here: http://nbviewer.ipython.org/cb6e9b476a41586958b5
Reported here: http://stackoverflow.com/questions/18721547/armax-model-forecasting-leads-to-valueerror-matrices-are-not-aligned-when-pas

Replicate

```
y = np.random.random(100)
x = np.random.random(100)
mod = sm.tsa.ARMA(y, (2,1), x).fit()
newx = np.random.random(12)
```

This breaks because we need to ensure that exog is 2d.

```
mod.forecast(steps=12, alpha=.05, exog=newx)
```

This gets further but falls down later

```
mod.forecast(steps=12, alpha=.05, exog=newx[:,None])
```

Need to investigate what's going on.



Discussion:
It falls down because you need to pass in past data too. If you want to predict 12 steps ahead with an ARMAX(2,q) model then you need to pass in 14 exogenous observations. I'm going to fix the dims check in exog and add this to the docs.


Resolving patch:
diff --git a/statsmodels/tsa/arima_model.py b/statsmodels/tsa/arima_model.py
--- a/statsmodels/tsa/arima_model.py
+++ b/statsmodels/tsa/arima_model.py
@@ -120,7 +120,10 @@
             want out of sample prediction.
         exog : array-like, optional
             If the model is an ARMAX and out-of-sample forecasting is
-            requested, exog must be given.
+            requested, exog must be given. Note that you'll need to pass
+            `k_ar` additional lags for any exogenous variables. E.g., if you
+            fit an ARMAX(2, q) model and want to predict 5 steps, you need 7
+            observations to do this.
         dynamic : bool, optional
             The `dynamic` keyword affects in-sample prediction. If dynamic
             is False, then the in-sample lagged values are used for
@@ -203,6 +206,15 @@ def _get_predict_out_of_sample(endog, p, q, k_trend, k_exog, start, errors,
         if k_exog > 0:
             #TODO: technically should only hold for MLE not
             # conditional model. See #274.
+            # ensure 2-d for conformability
+            if np.ndim(exog) == 1 and k_exog == 1:
+                # have a 1d series of observations -> 2d
+                exog = exog[:, None]
+            elif np.ndim(exog) == 1:
+                # should have a 1d row of exog -> 2d
+                if len(exog) != k_exog:
+                    raise ValueError("1d exog given and len(exog) != k_exog")
+                exog = exog[None, :]
             X = lagmat(np.dot(exog, exparams), p, original='in', trim='both')
             mu = trendparam * (1 - arparams.sum())
             # arparams were reversed in unpack for ease later
@@ -1337,7 +1349,10 @@ def forecast(self, steps=1, exog=None, alpha=.05):
         exog : array
             If the model is an ARMAX, you must provide out of sample
             values for the exogenous variables. This should not include
-            the constant.
+            the constant. Note that you'll need to pass `k_ar` additional
+            lags for any exogenous variables. E.g., if you fit an ARMAX(2, q)
+            model and want to predict 5 steps, you need 7 observations
+            to do this.
         alpha : float
             The confidence intervals for the forecasts are (1 - alpha) %
 


Test patch:
diff --git a/statsmodels/tsa/tests/test_arima.py b/statsmodels/tsa/tests/test_arima.py
--- a/statsmodels/tsa/tests/test_arima.py
+++ b/statsmodels/tsa/tests/test_arima.py
@@ -1822,6 +1822,15 @@ def test_arima_dataframe_integer_name():
     df = pandas.DataFrame(ts)
     mod = sm.tsa.ARIMA(df, (2, 0, 2))
 
+def test_arima_exog_predict_1d():
+    # test 1067
+    np.random.seed(12345)
+    y = np.random.random(100)
+    x = np.random.random(100)
+    mod = ARMA(y, (2, 1), x).fit(disp=-1)
+    newx = np.random.random(12)
+    results = mod.forecast(steps=10, alpha=0.05, exog=newx)
+
 if __name__ == "__main__":
     import nose
     nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb'], exit=False)