From 9cbaef6dd8df6b6fb06b8d1e53ae0d1a17d7370c Mon Sep 17 00:00:00 2001 From: Rick Chern Date: Mon, 22 May 2017 12:27:25 -0700 Subject: [PATCH 1/8] BUG Support empty DataFrame for datetime rolling window --- pandas/core/window.py | 2 +- pandas/tests/test_window.py | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pandas/core/window.py b/pandas/core/window.py index df8e0c05009f4..cf1bad706ae1d 100644 --- a/pandas/core/window.py +++ b/pandas/core/window.py @@ -1074,7 +1074,7 @@ def validate(self): super(Rolling, self).validate() # we allow rolling on a datetimelike index - if (self.is_datetimelike and + if ((self.obj.empty or self.is_datetimelike) and isinstance(self.window, (compat.string_types, DateOffset, timedelta))): diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 634cd5fe2586b..4a5ce5a1ebc3e 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -441,6 +441,16 @@ def test_closed(self): with pytest.raises(ValueError): df.rolling(window=3, closed='neither') + def test_empty_df_datetime_rolling_sum(self): + result = DataFrame().rolling('1s').sum() + expected = DataFrame() + tm.assert_frame_equal(result, expected) + + def test_empty_df_integer_rolling_sum(self): + result = DataFrame().rolling(1).sum() + expected = DataFrame() + tm.assert_frame_equal(result, expected) + class TestExpanding(Base): From d31b98360e9ac608db0ecbf0eab4894ba107d635 Mon Sep 17 00:00:00 2001 From: Rick Chern Date: Mon, 22 May 2017 12:43:37 -0700 Subject: [PATCH 2/8] BUG update release note for issue 15819 --- doc/source/whatsnew/v0.20.2.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.20.2.txt b/doc/source/whatsnew/v0.20.2.txt index e0857019d2fd4..b1ffc2c985d9f 100644 --- a/doc/source/whatsnew/v0.20.2.txt +++ b/doc/source/whatsnew/v0.20.2.txt @@ -37,6 +37,7 @@ Bug Fixes ~~~~~~~~~ - Bug in using ``pathlib.Path`` or ``py.path.local`` objects with io functions (:issue:`16291`) +- Bug creating rolling datetime rolling window on empty DataFrame (:issue:`15819`) Conversion ^^^^^^^^^^ From 5fb117085c2ae3f4b887880f493b68e67377e855 Mon Sep 17 00:00:00 2001 From: Rick Chern Date: Mon, 22 May 2017 16:01:05 -0700 Subject: [PATCH 3/8] Address code review comments --- doc/source/whatsnew/v0.20.2.txt | 2 +- pandas/tests/test_window.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.20.2.txt b/doc/source/whatsnew/v0.20.2.txt index b1ffc2c985d9f..dc6abcb3abdf0 100644 --- a/doc/source/whatsnew/v0.20.2.txt +++ b/doc/source/whatsnew/v0.20.2.txt @@ -37,7 +37,7 @@ Bug Fixes ~~~~~~~~~ - Bug in using ``pathlib.Path`` or ``py.path.local`` objects with io functions (:issue:`16291`) -- Bug creating rolling datetime rolling window on empty DataFrame (:issue:`15819`) +- Bug creating datetime rolling window on empty DataFrame (:issue:`15819`) Conversion ^^^^^^^^^^ diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 4a5ce5a1ebc3e..f5e6c902c6666 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -442,11 +442,15 @@ def test_closed(self): df.rolling(window=3, closed='neither') def test_empty_df_datetime_rolling_sum(self): + # Verifies that datetime rolling window can be applied to empty DataFrame + # GH 15819 result = DataFrame().rolling('1s').sum() expected = DataFrame() tm.assert_frame_equal(result, expected) def test_empty_df_integer_rolling_sum(self): + # Verifies that integer rolling window can be applied to empty DataFrame + # GH 15819 result = DataFrame().rolling(1).sum() expected = DataFrame() tm.assert_frame_equal(result, expected) From 670a33ae70cb4268871639da076bd319c0f788b8 Mon Sep 17 00:00:00 2001 From: Rick Chern Date: Tue, 23 May 2017 01:16:12 -0700 Subject: [PATCH 4/8] Add additional tests from code review and move release note to rolling window section --- doc/source/whatsnew/v0.20.2.txt | 4 +-- pandas/tests/test_window.py | 47 +++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/doc/source/whatsnew/v0.20.2.txt b/doc/source/whatsnew/v0.20.2.txt index dc6abcb3abdf0..d8910eaf7df28 100644 --- a/doc/source/whatsnew/v0.20.2.txt +++ b/doc/source/whatsnew/v0.20.2.txt @@ -37,7 +37,7 @@ Bug Fixes ~~~~~~~~~ - Bug in using ``pathlib.Path`` or ``py.path.local`` objects with io functions (:issue:`16291`) -- Bug creating datetime rolling window on empty DataFrame (:issue:`15819`) + Conversion ^^^^^^^^^^ @@ -69,7 +69,7 @@ Plotting Groupby/Resample/Rolling ^^^^^^^^^^^^^^^^^^^^^^^^ - +- Bug creating datetime rolling window on empty DataFrame (:issue:`15819`) Sparse diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index f5e6c902c6666..41204d3219746 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -444,15 +444,26 @@ def test_closed(self): def test_empty_df_datetime_rolling_sum(self): # Verifies that datetime rolling window can be applied to empty DataFrame # GH 15819 - result = DataFrame().rolling('1s').sum() expected = DataFrame() + result = DataFrame().rolling('1s').sum() tm.assert_frame_equal(result, expected) def test_empty_df_integer_rolling_sum(self): # Verifies that integer rolling window can be applied to empty DataFrame # GH 15819 - result = DataFrame().rolling(1).sum() expected = DataFrame() + result = DataFrame().rolling(1).sum() + tm.assert_frame_equal(result, expected) + + def test_empty_df_datetime_index_rolling_sum(self): + # Verifies that integer and datetime rolling windows can be applied to empty DataFrame with datetime index + # GH 15819 + expected = DataFrame(index=pd.DatetimeIndex([])) + + result = DataFrame(index=pd.DatetimeIndex([])).rolling('1s').sum() + tm.assert_frame_equal(result, expected) + + result = DataFrame(index=pd.DatetimeIndex([])).rolling(1).sum() tm.assert_frame_equal(result, expected) @@ -497,6 +508,38 @@ def test_numpy_compat(self): tm.assert_raises_regex(UnsupportedFunctionCall, msg, getattr(e, func), dtype=np.float64) + @pytest.mark.xfail(reason="Open issue GH 16425") + def test_empty_df_datetime_expanding_sum(self): + # Verifies that datetime expanding window can be applied to empty DataFrame + # GH 15819 + # GH 16425 + expected = DataFrame() + result = DataFrame().expanding('1s').sum() + tm.assert_frame_equal(result, expected) + + def test_empty_df_integer_expanding_sum(self): + # Verifies that integer expanding window can be applied to empty DataFrame + # GH 15819 + expected = DataFrame() + result = DataFrame().expanding(1).sum() + tm.assert_frame_equal(result, expected) + + @pytest.mark.xfail(reason="Open issue GH 16425") + def test_empty_df_datetime_index_datetime_expanding_sum(self): + # Verifies that datetime expanding window can be applied to empty DataFrame with datetime index + # GH 15819 + # GH 16425 + expected = DataFrame(index=pd.DatetimeIndex([])) + result = DataFrame(index=pd.DatetimeIndex([])).expanding('1s').sum() + tm.assert_frame_equal(result, expected) + + def test_empty_df_datetime_index_integer_expanding_sum(self): + # Verifies that integer expanding window can be applied to empty DataFrame with datetime index + # GH 15819 + expected = DataFrame(index=pd.DatetimeIndex([])) + result = DataFrame(index=pd.DatetimeIndex([])).expanding(1).sum() + tm.assert_frame_equal(result, expected) + class TestEWM(Base): From e9136649661773892dfe591e99cec53ae5db3d4a Mon Sep 17 00:00:00 2001 From: Rick Chern Date: Tue, 23 May 2017 01:22:20 -0700 Subject: [PATCH 5/8] Separate TestRolling.test_empty_df_datetime_index_rolling_sum() into 2 tests --- pandas/tests/test_window.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 41204d3219746..e8f7730d31cca 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -455,14 +455,17 @@ def test_empty_df_integer_rolling_sum(self): result = DataFrame().rolling(1).sum() tm.assert_frame_equal(result, expected) - def test_empty_df_datetime_index_rolling_sum(self): + def test_empty_df_datetime_index_datetime_rolling_sum(self): # Verifies that integer and datetime rolling windows can be applied to empty DataFrame with datetime index # GH 15819 expected = DataFrame(index=pd.DatetimeIndex([])) - result = DataFrame(index=pd.DatetimeIndex([])).rolling('1s').sum() tm.assert_frame_equal(result, expected) + def test_empty_df_datetime_index_integer_rolling_sum(self): + # Verifies that integer and datetime rolling windows can be applied to empty DataFrame with datetime index + # GH 15819 + expected = DataFrame(index=pd.DatetimeIndex([])) result = DataFrame(index=pd.DatetimeIndex([])).rolling(1).sum() tm.assert_frame_equal(result, expected) From 985522f3d0be01fbcb7a842d843f56895c56c37f Mon Sep 17 00:00:00 2001 From: Rick Chern Date: Tue, 23 May 2017 18:17:50 -0700 Subject: [PATCH 6/8] Combine tests into parameterized tests; update grammar in release note --- doc/source/whatsnew/v0.20.2.txt | 2 +- pandas/tests/test_window.py | 62 ++++++++++++--------------------- 2 files changed, 23 insertions(+), 41 deletions(-) diff --git a/doc/source/whatsnew/v0.20.2.txt b/doc/source/whatsnew/v0.20.2.txt index d8910eaf7df28..03afc11156cc2 100644 --- a/doc/source/whatsnew/v0.20.2.txt +++ b/doc/source/whatsnew/v0.20.2.txt @@ -69,7 +69,7 @@ Plotting Groupby/Resample/Rolling ^^^^^^^^^^^^^^^^^^^^^^^^ -- Bug creating datetime rolling window on empty DataFrame (:issue:`15819`) +- Bug creating datetime rolling window on an empty DataFrame (:issue:`15819`) Sparse diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index e8f7730d31cca..d316948fba399 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -441,32 +441,17 @@ def test_closed(self): with pytest.raises(ValueError): df.rolling(window=3, closed='neither') - def test_empty_df_datetime_rolling_sum(self): - # Verifies that datetime rolling window can be applied to empty DataFrame + @pytest.mark.parametrize('roller', ['1s', 1]) + def tests_empty_df_rolling(self, roller): + # Verifies that datetime and integer rolling windows can be applied to empty DataFrames # GH 15819 expected = DataFrame() - result = DataFrame().rolling('1s').sum() + result = DataFrame().rolling(roller).sum() tm.assert_frame_equal(result, expected) - def test_empty_df_integer_rolling_sum(self): - # Verifies that integer rolling window can be applied to empty DataFrame - # GH 15819 - expected = DataFrame() - result = DataFrame().rolling(1).sum() - tm.assert_frame_equal(result, expected) - - def test_empty_df_datetime_index_datetime_rolling_sum(self): - # Verifies that integer and datetime rolling windows can be applied to empty DataFrame with datetime index - # GH 15819 + # Verified that datetime and integer rolling windows can be applied to empty DataFrames with datetime index expected = DataFrame(index=pd.DatetimeIndex([])) - result = DataFrame(index=pd.DatetimeIndex([])).rolling('1s').sum() - tm.assert_frame_equal(result, expected) - - def test_empty_df_datetime_index_integer_rolling_sum(self): - # Verifies that integer and datetime rolling windows can be applied to empty DataFrame with datetime index - # GH 15819 - expected = DataFrame(index=pd.DatetimeIndex([])) - result = DataFrame(index=pd.DatetimeIndex([])).rolling(1).sum() + result = DataFrame(index=pd.DatetimeIndex([])).rolling(roller).sum() tm.assert_frame_equal(result, expected) @@ -511,36 +496,33 @@ def test_numpy_compat(self): tm.assert_raises_regex(UnsupportedFunctionCall, msg, getattr(e, func), dtype=np.float64) - @pytest.mark.xfail(reason="Open issue GH 16425") - def test_empty_df_datetime_expanding_sum(self): - # Verifies that datetime expanding window can be applied to empty DataFrame + # TODO: GH 16425: Add '1s' datetime expander when GH 16425 is resolved + @pytest.mark.parametrize('roller', [1]) + def tests_empty_df_expanding(self, expander): + # Verifies that datetime and integer expanding windows can be applied to empty DataFrames # GH 15819 - # GH 16425 expected = DataFrame() - result = DataFrame().expanding('1s').sum() + result = DataFrame().expanding(expander).sum() tm.assert_frame_equal(result, expected) - def test_empty_df_integer_expanding_sum(self): - # Verifies that integer expanding window can be applied to empty DataFrame - # GH 15819 - expected = DataFrame() - result = DataFrame().expanding(1).sum() + # Verified that datetime and integer expanding windows can be applied to empty DataFrames with datetime index + expected = DataFrame(index=pd.DatetimeIndex([])) + result = DataFrame(index=pd.DatetimeIndex([])).expanding(expander).sum() tm.assert_frame_equal(result, expected) + # TODO: GH 16425: Remove this test and add '1s' to roller parameter of test_empty_df_expanding() parameter + # when GH 16425 is resolved @pytest.mark.xfail(reason="Open issue GH 16425") - def test_empty_df_datetime_index_datetime_expanding_sum(self): - # Verifies that datetime expanding window can be applied to empty DataFrame with datetime index + def tests_empty_df_expanding_datetime(self): + # Verifies that datetime and integer expanding windows can be applied to empty DataFrames # GH 15819 - # GH 16425 - expected = DataFrame(index=pd.DatetimeIndex([])) - result = DataFrame(index=pd.DatetimeIndex([])).expanding('1s').sum() + expected = DataFrame() + result = DataFrame().expanding('1s').sum() tm.assert_frame_equal(result, expected) - def test_empty_df_datetime_index_integer_expanding_sum(self): - # Verifies that integer expanding window can be applied to empty DataFrame with datetime index - # GH 15819 + # Verified that datetime and integer expanding windows can be applied to empty DataFrames with datetime index expected = DataFrame(index=pd.DatetimeIndex([])) - result = DataFrame(index=pd.DatetimeIndex([])).expanding(1).sum() + result = DataFrame(index=pd.DatetimeIndex([])).expanding('1s').sum() tm.assert_frame_equal(result, expected) From 6007654f6520148f618a2dd11e669acea4e8eddc Mon Sep 17 00:00:00 2001 From: Rick Chern Date: Tue, 23 May 2017 18:19:42 -0700 Subject: [PATCH 7/8] Fix typo in comment --- pandas/tests/test_window.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index d316948fba399..45edd603b2900 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -449,7 +449,7 @@ def tests_empty_df_rolling(self, roller): result = DataFrame().rolling(roller).sum() tm.assert_frame_equal(result, expected) - # Verified that datetime and integer rolling windows can be applied to empty DataFrames with datetime index + # Verifies that datetime and integer rolling windows can be applied to empty DataFrames with datetime index expected = DataFrame(index=pd.DatetimeIndex([])) result = DataFrame(index=pd.DatetimeIndex([])).rolling(roller).sum() tm.assert_frame_equal(result, expected) @@ -497,7 +497,7 @@ def test_numpy_compat(self): getattr(e, func), dtype=np.float64) # TODO: GH 16425: Add '1s' datetime expander when GH 16425 is resolved - @pytest.mark.parametrize('roller', [1]) + @pytest.mark.parametrize('expander', [1]) def tests_empty_df_expanding(self, expander): # Verifies that datetime and integer expanding windows can be applied to empty DataFrames # GH 15819 @@ -505,7 +505,7 @@ def tests_empty_df_expanding(self, expander): result = DataFrame().expanding(expander).sum() tm.assert_frame_equal(result, expected) - # Verified that datetime and integer expanding windows can be applied to empty DataFrames with datetime index + # Verifies that datetime and integer expanding windows can be applied to empty DataFrames with datetime index expected = DataFrame(index=pd.DatetimeIndex([])) result = DataFrame(index=pd.DatetimeIndex([])).expanding(expander).sum() tm.assert_frame_equal(result, expected) @@ -520,7 +520,7 @@ def tests_empty_df_expanding_datetime(self): result = DataFrame().expanding('1s').sum() tm.assert_frame_equal(result, expected) - # Verified that datetime and integer expanding windows can be applied to empty DataFrames with datetime index + # Verifies that datetime and integer expanding windows can be applied to empty DataFrames with datetime index expected = DataFrame(index=pd.DatetimeIndex([])) result = DataFrame(index=pd.DatetimeIndex([])).expanding('1s').sum() tm.assert_frame_equal(result, expected) From 4a81a5e3dbce640212381e2d73713cc34dc59943 Mon Sep 17 00:00:00 2001 From: Rick Chern Date: Wed, 24 May 2017 23:47:47 -0700 Subject: [PATCH 8/8] Address code review comments --- pandas/tests/test_window.py | 38 ++++++++++++++----------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 45edd603b2900..6a640d62108b3 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -443,13 +443,14 @@ def test_closed(self): @pytest.mark.parametrize('roller', ['1s', 1]) def tests_empty_df_rolling(self, roller): - # Verifies that datetime and integer rolling windows can be applied to empty DataFrames - # GH 15819 + # GH 15819 Verifies that datetime and integer rolling windows can be + # applied to empty DataFrames expected = DataFrame() result = DataFrame().rolling(roller).sum() tm.assert_frame_equal(result, expected) - # Verifies that datetime and integer rolling windows can be applied to empty DataFrames with datetime index + # Verifies that datetime and integer rolling windows can be applied to + # empty DataFrames with datetime index expected = DataFrame(index=pd.DatetimeIndex([])) result = DataFrame(index=pd.DatetimeIndex([])).rolling(roller).sum() tm.assert_frame_equal(result, expected) @@ -496,33 +497,22 @@ def test_numpy_compat(self): tm.assert_raises_regex(UnsupportedFunctionCall, msg, getattr(e, func), dtype=np.float64) - # TODO: GH 16425: Add '1s' datetime expander when GH 16425 is resolved - @pytest.mark.parametrize('expander', [1]) + @pytest.mark.parametrize( + 'expander', + [1, pytest.mark.xfail( + reason='GH 16425 expanding with offset not supported')('1s')]) def tests_empty_df_expanding(self, expander): - # Verifies that datetime and integer expanding windows can be applied to empty DataFrames - # GH 15819 + # GH 15819 Verifies that datetime and integer expanding windows can be + # applied to empty DataFrames expected = DataFrame() result = DataFrame().expanding(expander).sum() tm.assert_frame_equal(result, expected) - # Verifies that datetime and integer expanding windows can be applied to empty DataFrames with datetime index - expected = DataFrame(index=pd.DatetimeIndex([])) - result = DataFrame(index=pd.DatetimeIndex([])).expanding(expander).sum() - tm.assert_frame_equal(result, expected) - - # TODO: GH 16425: Remove this test and add '1s' to roller parameter of test_empty_df_expanding() parameter - # when GH 16425 is resolved - @pytest.mark.xfail(reason="Open issue GH 16425") - def tests_empty_df_expanding_datetime(self): - # Verifies that datetime and integer expanding windows can be applied to empty DataFrames - # GH 15819 - expected = DataFrame() - result = DataFrame().expanding('1s').sum() - tm.assert_frame_equal(result, expected) - - # Verifies that datetime and integer expanding windows can be applied to empty DataFrames with datetime index + # Verifies that datetime and integer expanding windows can be applied + # to empty DataFrames with datetime index expected = DataFrame(index=pd.DatetimeIndex([])) - result = DataFrame(index=pd.DatetimeIndex([])).expanding('1s').sum() + result = DataFrame( + index=pd.DatetimeIndex([])).expanding(expander).sum() tm.assert_frame_equal(result, expected)