Repository: statsmodels/statsmodels

Issue:
Wrong return value for statsmodels.tsa.stattools.levinson_durbin
The documentation states that the last column of the return value phi contains the AR estimates with added a leading 1.
However, in the code one reads, before the return
    pacf_[0] = 1.
so it seems that a leading 1 has been placed in the wrong variable.
As a check, the entry phi[:,-1] results identically zero.



Discussion:
I need to look at the actual results. I thought this has enough test coverage that it should be correct, unless it's in a part that we don't use.

Do you have a runnable example so I don't have to find one?

AFAICS, there is no test coverage for this. Only pacf seems to be used from levinson_durbin.
So bug is very likely.

I think `pacf_[0] = 1.`  is correct because the 1 is for lag 0.

I'm not sure or don't remember about the phi.

Sorry, I will provide a test example as soon as possible; I need to extract a runnable piece of code from a larger project, and I cannot right now.
However, it seems reasonable to have a leading 1 also in phi[:,-1], as stated in the documentation, since this is a column returning the final AR coefficients, and this would make them readily usable in scipy.signal.lfilter, which wants the leading 1.

A correction; actually the phi coefficients would have to be negated, before inserting a leading 1, if they were to be used as AR coefficients in filtering; I promise, I will provide an example, don't spend time on this before I send one!

It will be possible to just use a sample dataset or test case for something else for this.

One thing that we have to watch out for with ar coefficients is whether they are left side or right side, i.e. if they should be the negative if we add them to the lag polynomial for lfilter.
We use both ar lag polynomial and ar_coeffs with  `ar = [1, - ar_coeffs]` when we switch representation in various models and helper functions.

simultaneous comments :)

Correct, the phi parameters appear to be RHS, and adding a leading 1 would be inconsistent, whereas adding a leading -1 would make things even more confusing for the end user!
Perhaps the cleanest solution is to fix the documentation about the return value phi. But again, I'll send an example tomorrow, after meeting my deadline.

As a test case Yule-Walker and levinson_durbin should give the same arcoeffs, except for numerical noise, e.g. `class TestPACF(CheckCorrGram):` for pacf.

check for 0.9. this issue didn't have labels and got lost
I'm changing this to a `type-test`.

AFAICS, only pacf has unit tests

The returned phi is the working array and we don't change that.
The other returns have been extracted from the two working arrays to have interpretable results
```
    sigma_v = sig[-1]
    arcoefs = phi[1:, -1]
    pacf_ = np.diag(phi).copy()
    pacf_[0] = 1.
    return sigma_v, arcoefs, pacf_, sig, phi
```

Resolving patch:
diff --git a/statsmodels/tsa/stattools.py b/statsmodels/tsa/stattools.py
--- a/statsmodels/tsa/stattools.py
+++ b/statsmodels/tsa/stattools.py
@@ -717,7 +717,8 @@ def periodogram(X):
 #copied from nitime and statsmodels\sandbox\tsa\examples\try_ld_nitime.py
 #TODO: check what to return, for testing and trying out returns everything
 def levinson_durbin(s, nlags=10, isacov=False):
-    '''Levinson-Durbin recursion for autoregressive processes
+    """
+    Levinson-Durbin recursion for autoregressive processes
 
     Parameters
     ----------
@@ -736,14 +737,14 @@ def levinson_durbin(s, nlags=10, isacov=False):
     sigma_v : float
         estimate of the error variance ?
     arcoefs : ndarray
-        estimate of the autoregressive coefficients
+        estimate of the autoregressive coefficients for a model including nlags
     pacf : ndarray
         partial autocorrelation function
     sigma : ndarray
         entire sigma array from intermediate result, last value is sigma_v
     phi : ndarray
         entire phi array from intermediate result, last column contains
-        autoregressive coefficients for AR(nlags) with a leading 1
+        autoregressive coefficients for AR(nlags)
 
     Notes
     -----
@@ -753,15 +754,10 @@ def levinson_durbin(s, nlags=10, isacov=False):
     If this function is called with the time series (isacov=False), then the
     sample autocovariance function is calculated with the default options
     (biased, no fft).
-    '''
+    """
     s = np.asarray(s)
-    order = nlags  # rename compared to nitime
-    #from nitime
+    order = nlags
 
-    ##if sxx is not None and type(sxx) == np.ndarray:
-    ##    sxx_m = sxx[:order+1]
-    ##else:
-    ##    sxx_m = ut.autocov(s)[:order+1]
     if isacov:
         sxx_m = s
     else:


Test patch:
diff --git a/statsmodels/tsa/tests/test_stattools.py b/statsmodels/tsa/tests/test_stattools.py
--- a/statsmodels/tsa/tests/test_stattools.py
+++ b/statsmodels/tsa/tests/test_stattools.py
@@ -1,21 +1,22 @@
-from statsmodels.compat.numpy import recarray_select
+import os
+import warnings
 
-from statsmodels.compat.python import lrange
-from statsmodels.tools.sm_exceptions import ColinearityWarning
-from statsmodels.tsa.stattools import (adfuller, acf, pacf_ols, pacf_yw,
-                                               pacf, grangercausalitytests,
-                                               coint, acovf, kpss, ResultsStore,
-                                               arma_order_select_ic)
 import numpy as np
 import pandas as pd
 import pytest
-from numpy.testing import (assert_almost_equal, assert_equal, assert_warns,
-                           assert_raises, assert_, assert_allclose)
-from statsmodels.datasets import macrodata, sunspots
+from numpy.testing import (assert_almost_equal, assert_equal, assert_raises, assert_,
+                           assert_allclose)
 from pandas import Series, DatetimeIndex, DataFrame
-import os
-import warnings
+
+from statsmodels.compat.numpy import recarray_select
+from statsmodels.compat.python import lrange
+from statsmodels.datasets import macrodata, sunspots
+from statsmodels.tools.sm_exceptions import ColinearityWarning
 from statsmodels.tools.sm_exceptions import MissingDataError
+from statsmodels.tsa.stattools import (adfuller, acf, pacf_yw,
+                                       pacf, grangercausalitytests,
+                                       coint, acovf, kpss, arma_order_select_ic,
+                                       levinson_durbin)
 
 DECIMAL_8 = 8
 DECIMAL_6 = 6
@@ -503,7 +504,6 @@ def test_acovf_fft_vs_convolution():
 def test_arma_order_select_ic():
     # smoke test, assumes info-criteria are right
     from statsmodels.tsa.arima_process import arma_generate_sample
-    import statsmodels.api as sm
 
     arparams = np.array([.75, -.25])
     maparams = np.array([.65, .35])
@@ -568,6 +568,18 @@ def test_acf_fft_dataframe():
     result = acf(sunspots.load_pandas().data[['SUNACTIVITY']], fft=True)
     assert_equal(result.ndim, 1)
 
+
+def test_levinson_durbin_acov():
+    rho = 0.9
+    m = 20
+    acov = rho**np.arange(200)
+    sigma2_eps, ar, pacf, _, _ = levinson_durbin(acov, m, isacov=True)
+    assert_allclose(sigma2_eps, 1 - rho ** 2)
+    assert_allclose(ar, np.array([rho] + [0] * (m - 1)), atol=1e-8)
+    assert_allclose(pacf, np.array([1, rho] + [0] * (m - 1)), atol=1e-8)
+
+
 if __name__=="__main__":
     import pytest
     pytest.main([__file__, '-vvs', '-x', '--pdb'])
+