From fe9e31023ad704559bea6f3358be674684bb3aee Mon Sep 17 00:00:00 2001 From: Michael Selik Date: Wed, 9 May 2018 15:03:56 -0700 Subject: [PATCH 1/7] ENH: Raise useful error when iterating a Window Until Issue #11704 is completed, raise a NotImplementedError to provide a more clear error message when attempting to iterate over a Rolling or Expanding window. --- pandas/core/window.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/core/window.py b/pandas/core/window.py index 5fd054b1930e6..9a81c6e9fe145 100644 --- a/pandas/core/window.py +++ b/pandas/core/window.py @@ -181,6 +181,10 @@ def __unicode__(self): return "{klass} [{attrs}]".format(klass=self._window_type, attrs=','.join(attrs)) + def __iter__(self): + url = 'https://github.com/pandas-dev/pandas/issues/11704' + raise NotImplementedError('See issue #11704 %s' % (url,)) + def _get_index(self, index=None): """ Return index as ndarrays From 9fd89dcf3c69df2113a7dddfa2da5cd422635af9 Mon Sep 17 00:00:00 2001 From: Michael Selik Date: Thu, 10 May 2018 10:26:01 -0700 Subject: [PATCH 2/7] Test that iteration raises NotImplemented --- pandas/tests/test_window.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 93f637a561718..5e3d5a4e4759d 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -46,6 +46,27 @@ def win_types_special(request): return request.param +# Issue 11704: Iteration over a Window + +@pytest.fixture +def series(): + return pd.Series([1, 2, 3, 4]) + +@pytest.fixture +def frame(): + return pd.DataFrame({'a': [1, 2, 3, 4], 'b': [10, 20, 30, 40]}) + +@pytest.mark.parametrize('which', [series(), frame()]) +def test_rolling_iterator(which): + with pytest.raises(NotImplementedError): + iter(which.rolling(2)) + +@pytest.mark.parametrize('which', [series(), frame()]) +def test_expanding_iterator(which): + with pytest.raises(NotImplementedError): + iter(which.expanding()) + + class Base(object): _nan_locs = np.arange(20, 40) From 4ac67f07bf4ee826104d7b314b4921e9fef43e02 Mon Sep 17 00:00:00 2001 From: Michael Selik Date: Thu, 10 May 2018 10:26:52 -0700 Subject: [PATCH 3/7] Note window iteration raises NotImplemented --- doc/source/whatsnew/v0.23.0.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 32f7447e5ef77..b8c2a8f4c661b 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -966,6 +966,7 @@ Other API Changes - Constructing a Series from a list of length 1 no longer broadcasts this list when a longer index is specified (:issue:`19714`, :issue:`20391`). - :func:`DataFrame.to_dict` with ``orient='index'`` no longer casts int columns to float for a DataFrame with only int and float columns (:issue:`18580`) - A user-defined-function that is passed to :func:`Series.rolling().aggregate() `, :func:`DataFrame.rolling().aggregate() `, or its expanding cousins, will now *always* be passed a ``Series``, rather than a ``np.array``; ``.apply()`` only has the ``raw`` keyword, see :ref:`here `. This is consistent with the signatures of ``.aggregate()`` across pandas (:issue:`20584`) +- Window types, such as Rolling and Expanding, raise `NotImplementedError` upon iteration. This will ideally be replaced by mimicking the (key, group) iteration of GroupBy (:issue:`11704`). .. _whatsnew_0230.deprecations: From 15224fedcb112b810dcb628376f05873ad07e17f Mon Sep 17 00:00:00 2001 From: Michael Selik Date: Thu, 10 May 2018 10:28:43 -0700 Subject: [PATCH 4/7] switch % to .format --- pandas/core/window.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/window.py b/pandas/core/window.py index 9a81c6e9fe145..015e7f7913ed0 100644 --- a/pandas/core/window.py +++ b/pandas/core/window.py @@ -183,7 +183,7 @@ def __unicode__(self): def __iter__(self): url = 'https://github.com/pandas-dev/pandas/issues/11704' - raise NotImplementedError('See issue #11704 %s' % (url,)) + raise NotImplementedError('See issue #11704 {url}'.format(url=url)) def _get_index(self, index=None): """ From 4b44b059f5ea631be572f35bb25901f27cbb2cd4 Mon Sep 17 00:00:00 2001 From: Michael Selik Date: Sat, 12 May 2018 08:55:41 -0700 Subject: [PATCH 5/7] style change as per suggestion --- doc/source/whatsnew/v0.23.0.txt | 2 +- pandas/tests/test_window.py | 37 ++++++++++++++------------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index b8c2a8f4c661b..8d20d7b6b78bd 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -966,7 +966,7 @@ Other API Changes - Constructing a Series from a list of length 1 no longer broadcasts this list when a longer index is specified (:issue:`19714`, :issue:`20391`). - :func:`DataFrame.to_dict` with ``orient='index'`` no longer casts int columns to float for a DataFrame with only int and float columns (:issue:`18580`) - A user-defined-function that is passed to :func:`Series.rolling().aggregate() `, :func:`DataFrame.rolling().aggregate() `, or its expanding cousins, will now *always* be passed a ``Series``, rather than a ``np.array``; ``.apply()`` only has the ``raw`` keyword, see :ref:`here `. This is consistent with the signatures of ``.aggregate()`` across pandas (:issue:`20584`) -- Window types, such as Rolling and Expanding, raise `NotImplementedError` upon iteration. This will ideally be replaced by mimicking the (key, group) iteration of GroupBy (:issue:`11704`). +- Rolling and Expanding types raise ``NotImplementedError`` upon iteration (:issue:`11704`). .. _whatsnew_0230.deprecations: diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 5e3d5a4e4759d..f95541322ab80 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -46,27 +46,6 @@ def win_types_special(request): return request.param -# Issue 11704: Iteration over a Window - -@pytest.fixture -def series(): - return pd.Series([1, 2, 3, 4]) - -@pytest.fixture -def frame(): - return pd.DataFrame({'a': [1, 2, 3, 4], 'b': [10, 20, 30, 40]}) - -@pytest.mark.parametrize('which', [series(), frame()]) -def test_rolling_iterator(which): - with pytest.raises(NotImplementedError): - iter(which.rolling(2)) - -@pytest.mark.parametrize('which', [series(), frame()]) -def test_expanding_iterator(which): - with pytest.raises(NotImplementedError): - iter(which.expanding()) - - class Base(object): _nan_locs = np.arange(20, 40) @@ -533,6 +512,14 @@ def test_multi_index_names(self): tm.assert_index_equal(result.columns, df.columns) assert result.index.names == [None, '1', '2'] + @pytest.mark.parametrize('cls', [pd.Series, pd.DataFrame]) + def test_iter_raises(cls): + # https://github.com/pandas-dev/pandas/issues/11704 + # Iteration over a Window + obj = cls([1, 2, 3, 4]) + with pytest.raises(NotImplementedError): + iter(obj.rolling(2)) + class TestExpanding(Base): @@ -611,6 +598,14 @@ def test_missing_minp_zero(self): expected = pd.Series([np.nan]) tm.assert_series_equal(result, expected) + @pytest.mark.parametrize('cls', [pd.Series, pd.DataFrame]) + def test_iter_raises(cls): + # https://github.com/pandas-dev/pandas/issues/11704 + # Iteration over a Window + obj = cls([1, 2, 3, 4]) + with pytest.raises(NotImplementedError): + iter(obj.expanding(2)) + class TestEWM(Base): From 1bcaa7f443892aba4894b84baa42c0808b977b03 Mon Sep 17 00:00:00 2001 From: Michael Selik Date: Sat, 12 May 2018 09:00:41 -0700 Subject: [PATCH 6/7] fix testfunc parameters --- pandas/tests/test_window.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index f95541322ab80..4e185b20caf25 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -513,7 +513,7 @@ def test_multi_index_names(self): assert result.index.names == [None, '1', '2'] @pytest.mark.parametrize('cls', [pd.Series, pd.DataFrame]) - def test_iter_raises(cls): + def test_iter_raises(self, cls): # https://github.com/pandas-dev/pandas/issues/11704 # Iteration over a Window obj = cls([1, 2, 3, 4]) @@ -599,7 +599,7 @@ def test_missing_minp_zero(self): tm.assert_series_equal(result, expected) @pytest.mark.parametrize('cls', [pd.Series, pd.DataFrame]) - def test_iter_raises(cls): + def test_iter_raises(self, cls): # https://github.com/pandas-dev/pandas/issues/11704 # Iteration over a Window obj = cls([1, 2, 3, 4]) From 6bd748db1812cab462fba63f4c75ab76394c6ca1 Mon Sep 17 00:00:00 2001 From: Michael Selik Date: Sat, 12 May 2018 09:13:34 -0700 Subject: [PATCH 7/7] s/cls/klass/g --- pandas/tests/test_window.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 4e185b20caf25..d8e90ae0e1b35 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -512,11 +512,11 @@ def test_multi_index_names(self): tm.assert_index_equal(result.columns, df.columns) assert result.index.names == [None, '1', '2'] - @pytest.mark.parametrize('cls', [pd.Series, pd.DataFrame]) - def test_iter_raises(self, cls): + @pytest.mark.parametrize('klass', [pd.Series, pd.DataFrame]) + def test_iter_raises(self, klass): # https://github.com/pandas-dev/pandas/issues/11704 # Iteration over a Window - obj = cls([1, 2, 3, 4]) + obj = klass([1, 2, 3, 4]) with pytest.raises(NotImplementedError): iter(obj.rolling(2)) @@ -598,11 +598,11 @@ def test_missing_minp_zero(self): expected = pd.Series([np.nan]) tm.assert_series_equal(result, expected) - @pytest.mark.parametrize('cls', [pd.Series, pd.DataFrame]) - def test_iter_raises(self, cls): + @pytest.mark.parametrize('klass', [pd.Series, pd.DataFrame]) + def test_iter_raises(self, klass): # https://github.com/pandas-dev/pandas/issues/11704 # Iteration over a Window - obj = cls([1, 2, 3, 4]) + obj = klass([1, 2, 3, 4]) with pytest.raises(NotImplementedError): iter(obj.expanding(2))