Rolling window polynomial fit in pandas
Question: I am trying to compute coefficients from a _n_ -degree polynomial applied to a
_t_ -day window of a time series. However, I receive an exception `TypeError:
only length-1 arrays can be converted to Python scalars`.

My versions are:

  * Python 2.7.8
  * pandas version 0.14.1
  * numpy version 1.9.0 

The code:

    
    
    import pandas as pd
    import numpy as np
    my_ts = pd.Series(data = np.random.normal(size = 365 * 2), index = pd.date_range(start = '2013-01-01', periods = 365 * 2))
    coefs = pd.rolling_apply(my_ts, 21, lambda x: np.polyfit(range(len(x)), x, 3))
    

Yet, when I wrap `np.polyfit` so that it returns only one coefficient,
`rolling_apply` has no issue.

    
    
    def pf_wrapper(x):
        coef_lst = np.polyfit(range(len(x)), x, 3)
        return coef_lst[0]
    coefs = pd.rolling_apply(my_ts, 21, pf_wrapper)
    

UPDATE:

Since `pd.rolling_apply()` is unable to return a non-scalar, my current
solution is the following:

    
    
    def get_beta(ts, deg):
        coefs = polyfit(range(len(ts)), ts, deg = 3)[::-1]
        return coefs[deg]
    
    b0 = pd.rolling_apply(my_ts, 21, lambda x: get_beta(x, 0))
    ...
    b3 = pd.rolling_apply(my_ts, 21, lambda x: get_beta(x, 3))
    


Answer: I don't think it is possible with `rolling_apply`. The
[documentation](http://pandas.pydata.org/pandas-
docs/stable/generated/pandas.stats.moments.rolling_apply.html) says that the
applied function "must produce a single value from an ndarray input". What it
seems to actually mean is "must produce a value _that is or can be converted
into a single float_ ". If you follow up on the full exception traceback it
leads you to this code in `algos.pyx`:

    
    
    output = np.empty(n, dtype=float)
    counts = roll_sum(np.isfinite(input).astype(float), win, minp)
    
    bufarr = np.empty(win, dtype=float)
    oldbuf = <float64_t*> bufarr.data
    
    n = len(input)
    for i from 0 <= i < int_min(win, n):
        if counts[i] >= minp:
            output[i] = func(input[int_max(i - win + 1, 0) : i + 1], *args,
                             **kwargs)
        else:
            output[i] = NaN
    

The error is raised on the line with `output[i] = func(...)`. You can see that
the output array is hardcoded to have dtype float. The error you receive is
the same as what you get if you attempt to convert a numpy array (of length
more than 1) to a float:

    
    
    >>> float(np.array([1, 2, 3]))
    Traceback (most recent call last):
      File "<pyshell#14>", line 1, in <module>
        float(np.array([1, 2, 3]))
    TypeError: only length-1 arrays can be converted to Python scalars
    

So what is happening is that it tries to assign the output of `polyfit` to a
single element of the float ndarray, and fails because the output of polyfit
is an array that can't be converted to a float.

This could be "fixed" by making `output` have dtype object, but this would
slow things way down.

I think you have to consider `rolling_apply` as usable only for functions that
return a single float. To support non-scalar outputs, you would have to roll
(har har) your own version of `rolling_apply`.

