From 99f498b8eb04f3ea464da489b49fc4268a29805d Mon Sep 17 00:00:00 2001 From: Radek Benes Date: Mon, 29 Apr 2019 21:11:29 +0200 Subject: [PATCH 1/4] Exponential window can be used --- pandas/core/window.py | 21 ++++++++++++++++----- pandas/tests/test_window.py | 13 +++++++++---- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/pandas/core/window.py b/pandas/core/window.py index ffb88b9c4eb65..f63693ed274c8 100644 --- a/pandas/core/window.py +++ b/pandas/core/window.py @@ -504,7 +504,8 @@ class Window(_Window): * ``kaiser`` (needs beta) * ``gaussian`` (needs std) * ``general_gaussian`` (needs power, width) - * ``slepian`` (needs width). + * ``slepian`` (needs width) + * ``exponential`` (needs tau), center is set to None. If ``win_type=None`` all points are evenly weighted. To learn more about different window types see `scipy.signal window functions @@ -623,20 +624,30 @@ def _validate_win_type(win_type, kwargs): arg_map = {'kaiser': ['beta'], 'gaussian': ['std'], 'general_gaussian': ['power', 'width'], - 'slepian': ['width']} + 'slepian': ['width'], + 'exponential': ['center', 'tau']} + immutable_args_map = {'exponential': {'center': None}} + if win_type in arg_map: + immutable_args = immutable_args_map.get(win_type, {}) return tuple([win_type] + _pop_args(win_type, arg_map[win_type], + immutable_args, kwargs)) + return win_type - def _pop_args(win_type, arg_names, kwargs): + def _pop_args(win_type, arg_names, immutable_args, kwargs): msg = '%s window requires %%s' % win_type all_args = [] for n in arg_names: - if n not in kwargs: + if n in immutable_args: + value = immutable_args[n] + elif n in kwargs: + value = kwargs.pop(n) + else: raise ValueError(msg % n) - all_args.append(kwargs.pop(n)) + all_args.append(value) return all_args win_type = _validate_win_type(self.win_type, kwargs) diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 1d5dd8c2bfcf8..bc6946cbade4c 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -42,7 +42,8 @@ def win_types(request): return request.param -@pytest.fixture(params=['kaiser', 'gaussian', 'general_gaussian']) +@pytest.fixture(params=['kaiser', 'gaussian', 'general_gaussian', + 'exponential']) def win_types_special(request): return request.param @@ -1260,7 +1261,8 @@ def test_cmov_window_special(self, win_types_special): kwds = { 'kaiser': {'beta': 1.}, 'gaussian': {'std': 1.}, - 'general_gaussian': {'power': 2., 'width': 2.}} + 'general_gaussian': {'power': 2., 'width': 2.}, + 'exponential': {'tau': 10}} vals = np.array([6.95, 15.21, 4.72, 9.12, 13.81, 13.49, 16.68, 9.48, 10.63, 14.48]) @@ -1271,7 +1273,9 @@ def test_cmov_window_special(self, win_types_special): 'general_gaussian': [np.nan, np.nan, 9.85011, 10.71589, 11.73161, 13.08516, 12.95111, 12.74577, np.nan, np.nan], 'kaiser': [np.nan, np.nan, 9.86851, 11.02969, 11.65161, 12.75129, - 12.90702, 12.83757, np.nan, np.nan] + 12.90702, 12.83757, np.nan, np.nan], + 'exponential': [np.nan, np.nan, 9.83364, 11.10472, 11.64551, + 12.66138, 12.92379, 12.83770, np.nan, np.nan], } xp = Series(xps[win_types_special]) @@ -1287,7 +1291,8 @@ def test_cmov_window_special_linear_range(self, win_types_special): 'kaiser': {'beta': 1.}, 'gaussian': {'std': 1.}, 'general_gaussian': {'power': 2., 'width': 2.}, - 'slepian': {'width': 0.5}} + 'slepian': {'width': 0.5}, + 'exponential': {'tau': 10}} vals = np.array(range(10), dtype=np.float) xp = vals.copy() From 1b3d957f1ca31af71a98a6d11f9a092b2bd5ffb2 Mon Sep 17 00:00:00 2001 From: Radek Benes Date: Mon, 29 Apr 2019 21:58:32 +0200 Subject: [PATCH 2/4] Whats new added --- doc/source/whatsnew/v0.25.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index a65b92737c220..820a74ef334c5 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -39,6 +39,7 @@ Other Enhancements - :class:`datetime.timezone` objects are now supported as arguments to timezone methods and constructors (:issue:`25065`) - :meth:`DataFrame.query` and :meth:`DataFrame.eval` now supports quoting column names with backticks to refer to names with spaces (:issue:`6508`) - :func:`merge_asof` now gives a more clear error message when merge keys are categoricals that are not equal (:issue:`26136`) +- :meth:`pandas.core.window.Rolling` supports exponential (or Poisson) window type (:issue:`21303`) .. _whatsnew_0250.api_breaking: From d867ad4989f54e928e2f3b0fe8195efc5c71b112 Mon Sep 17 00:00:00 2001 From: Radek Benes Date: Sat, 4 May 2019 21:13:13 +0200 Subject: [PATCH 3/4] Simplify --- pandas/core/window.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/pandas/core/window.py b/pandas/core/window.py index f63693ed274c8..2d7fdbeffbccc 100644 --- a/pandas/core/window.py +++ b/pandas/core/window.py @@ -625,29 +625,27 @@ def _validate_win_type(win_type, kwargs): 'gaussian': ['std'], 'general_gaussian': ['power', 'width'], 'slepian': ['width'], - 'exponential': ['center', 'tau']} - immutable_args_map = {'exponential': {'center': None}} + 'exponential': ['tau'], + } if win_type in arg_map: - immutable_args = immutable_args_map.get(win_type, {}) - return tuple([win_type] + _pop_args(win_type, - arg_map[win_type], - immutable_args, - kwargs)) + win_args = _pop_args(win_type, arg_map[win_type], kwargs) + if win_type == 'exponential': + # exponential window requires the first arg (center) + # to be set to None (necessary for symmetric window) + win_args.insert(0, None) + + return tuple([win_type] + win_args) return win_type - def _pop_args(win_type, arg_names, immutable_args, kwargs): + def _pop_args(win_type, arg_names, kwargs): msg = '%s window requires %%s' % win_type all_args = [] for n in arg_names: - if n in immutable_args: - value = immutable_args[n] - elif n in kwargs: - value = kwargs.pop(n) - else: + if n not in kwargs: raise ValueError(msg % n) - all_args.append(value) + all_args.append(kwargs.pop(n)) return all_args win_type = _validate_win_type(self.win_type, kwargs) From af964937da247e6939268ea72fbd68266c55a2f7 Mon Sep 17 00:00:00 2001 From: Radek Benes Date: Tue, 7 May 2019 07:30:13 +0200 Subject: [PATCH 4/4] computation.rst updated --- doc/source/user_guide/computation.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/user_guide/computation.rst b/doc/source/user_guide/computation.rst index c96e066a5874b..466486586f50b 100644 --- a/doc/source/user_guide/computation.rst +++ b/doc/source/user_guide/computation.rst @@ -365,7 +365,8 @@ The list of recognized types are the `scipy.signal window functions * ``kaiser`` (needs beta) * ``gaussian`` (needs std) * ``general_gaussian`` (needs power, width) -* ``slepian`` (needs width). +* ``slepian`` (needs width) +* ``exponential`` (needs tau). .. ipython:: python