related #2813, #4964 (somewhat)
At the moment rolling_apply (et al) the passed function has to return a value (unlike apply which can return a Series and overall return a DataFrame).
If you could pass it a Series you could, for example, do this:
from pandas.core.algorithms import value_counts
s = Series([1, 1, 2, 3, 1, 2, 3, 2, 1])
pd.rolling_apply(s, 3, value_counts)
from the mailing list.
Comment From: jreback
Here's the example, only issue is that you need to test first iteration to see what structure is returned
In [5]: s = Series([1, 1, 2, 3, 1, 2, 3, 2, 1])
In [6]: def f(x):
...: c = x.value_counts()
...: return 100*c/c.sum()
...:
In [7]: concat([ f(s.iloc[i:i+3]) for i in range(len(s)-3) ],axis=1)
Out[7]:
0 1 2 3 4 5
1 66 33 33 33 33 NaN
2 33 33 33 33 33 66
3 NaN 33 33 33 33 33
Comment From: WillAyd
A series can be produced now via the keyword argument raw=False
, though the original issue does not work on master with a relatively cryptic message:
>>>
s.rolling(3).apply(lambda x: x[:2], raw=False)
TypeError: cannot convert the series to <class 'float'>
Not sure it is even feasible to support non-reducing functions like value_counts
provided in the original message, but keeping open in case others have an idea on how to support
Comment From: mroeschke
Looks like there hasn't been a lot of demand for this feature and would increase the complexity greatly if apply could return arbitrary shaped results for each window, so closing for now. Can reopen if there's more interest