From b139cb14314fed2892dc3ed9de1956573eb4ac31 Mon Sep 17 00:00:00 2001 From: Yotam Reshef Date: Sat, 7 Jul 2018 23:01:45 +0300 Subject: [PATCH 01/10] ENH: between_time, at_time accept axis parameter --- pandas/core/generic.py | 24 +++++++++---- pandas/tests/frame/test_timeseries.py | 50 ++++++++++++++++++++++++++ pandas/tests/series/test_timeseries.py | 10 ++++++ 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 08d9191d72a8a..d3c9d1472dccb 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -7013,7 +7013,7 @@ def asfreq(self, freq, method=None, how=None, normalize=False, return asfreq(self, freq, method=method, how=how, normalize=normalize, fill_value=fill_value) - def at_time(self, time, asof=False): + def at_time(self, time, asof=False, axis=None): """ Select values at particular time of day (e.g. 9:30AM). @@ -7025,6 +7025,7 @@ def at_time(self, time, asof=False): Parameters ---------- time : datetime.time or string + axis : int or string axis name, optional Returns ------- @@ -7054,14 +7055,19 @@ def at_time(self, time, asof=False): DatetimeIndex.indexer_at_time : Get just the index locations for values at particular time of the day """ + if axis is None: + axis = self._stat_axis_number + axis = self._get_axis_number(axis) + try: - indexer = self.index.indexer_at_time(time, asof=asof) - return self._take(indexer) + index = self._get_axis(axis) + indexer = index.indexer_at_time(time, asof=asof) + return self._take(indexer, axis=axis) except AttributeError: raise TypeError('Index must be DatetimeIndex') def between_time(self, start_time, end_time, include_start=True, - include_end=True): + include_end=True, axis=None): """ Select values between particular times of the day (e.g., 9:00-9:30 AM). @@ -7079,6 +7085,7 @@ def between_time(self, start_time, end_time, include_start=True, end_time : datetime.time or string include_start : boolean, default True include_end : boolean, default True + axis : int or string axis name, optional Returns ------- @@ -7116,11 +7123,16 @@ def between_time(self, start_time, end_time, include_start=True, DatetimeIndex.indexer_between_time : Get just the index locations for values between particular times of the day """ + if axis is None: + axis = self._stat_axis_number + axis = self._get_axis_number(axis) + try: - indexer = self.index.indexer_between_time( + index = self._get_axis(axis) + indexer = index.indexer_between_time( start_time, end_time, include_start=include_start, include_end=include_end) - return self._take(indexer) + return self._take(indexer, axis=axis) except AttributeError: raise TypeError('Index must be DatetimeIndex') diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index b1d9d362d1402..aad2e74e46807 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -640,6 +640,22 @@ def test_at_time_raises(self): with pytest.raises(TypeError): # index is not a DatetimeIndex df.at_time('00:00') + def test_at_time_axis(self): + rng = date_range('1/1/2000', '1/5/2000', freq='5min') + ts = DataFrame(np.random.randn(len(rng), len(rng))) + + indices = rng[(rng.hour == 9) & (rng.minute == 30) & (rng.second == 0)] + + ts.index = rng + expected = ts.loc[indices] + result = ts.at_time('9:30', axis=0) + assert_frame_equal(result, expected) + + ts.columns = rng + expected = ts.loc[:,indices] + result = ts.at_time('9:30', axis=1) + assert_frame_equal(result, expected) + def test_between_time(self): rng = date_range('1/1/2000', '1/5/2000', freq='5min') ts = DataFrame(np.random.randn(len(rng), 2), index=rng) @@ -706,6 +722,40 @@ def test_between_time_raises(self): with pytest.raises(TypeError): # index is not a DatetimeIndex df.between_time(start_time='00:00', end_time='12:00') + def test_between_time_axis(self): + rng = date_range('1/1/2000', periods=100, freq='10min') + blank = np.arange(0,len(rng)) + stime, etime = ('08:00:00', '09:00:00') + dimn = (len(rng), len(rng)) + exp_len = 7 + + for time_index, time_col in product([True, False], [True, False]): + if time_index: + index = rng + else: + index = blank + if time_col: + col = rng + else: + col = blank + + ts = DataFrame(np.random.randn(*dimn), index=index, columns=col) + + if time_index: + assert len(ts.between_time(stime, etime)) == exp_len + assert len(ts.between_time(stime, etime, axis=0)) == exp_len + else: + pytest.raises(TypeError, ts.between_time, stime, etime) + pytest.raises(TypeError, ts.between_time, stime, etime, + axis=0) + + if time_col: + selected = ts.between_time(stime, etime, axis=1).columns + assert len(selected) == exp_len + else: + pytest.raises(TypeError, ts.between_time, stime, etime, + axis=1) + def test_operation_on_NaT(self): # Both NaT and Timestamp are in DataFrame. df = pd.DataFrame({'foo': [pd.NaT, pd.NaT, diff --git a/pandas/tests/series/test_timeseries.py b/pandas/tests/series/test_timeseries.py index 72492de4b1247..c76c21e57bcbe 100644 --- a/pandas/tests/series/test_timeseries.py +++ b/pandas/tests/series/test_timeseries.py @@ -825,6 +825,16 @@ def test_between_time_formats(self): for time_string in strings: assert len(ts.between_time(*time_string)) == expected_length + def test_between_time_axis(self): + rng = date_range('1/1/2000', periods=100, freq='10min') + ts = Series(np.random.randn(len(rng)), index=rng) + stime, etime = ('08:00:00', '09:00:00') + expected_length = 7 + + assert len(ts.between_time(stime, etime)) == expected_length + assert len(ts.between_time(stime, etime, axis=0)) == expected_length + pytest.raises(ValueError, ts.between_time, stime, etime, axis=1) + def test_to_period(self): from pandas.core.indexes.period import period_range From 51b7e61772dddd0eaa79c28d43d5d760c0f05d06 Mon Sep 17 00:00:00 2001 From: Yotam Reshef Date: Sat, 7 Jul 2018 23:20:21 +0300 Subject: [PATCH 02/10] PEP8 adjustment for ttests --- pandas/tests/frame/test_timeseries.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index aad2e74e46807..ebf101d60d164 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -652,7 +652,7 @@ def test_at_time_axis(self): assert_frame_equal(result, expected) ts.columns = rng - expected = ts.loc[:,indices] + expected = ts.loc[:, indices] result = ts.at_time('9:30', axis=1) assert_frame_equal(result, expected) @@ -724,11 +724,10 @@ def test_between_time_raises(self): def test_between_time_axis(self): rng = date_range('1/1/2000', periods=100, freq='10min') - blank = np.arange(0,len(rng)) + blank = np.arange(0, len(rng)) stime, etime = ('08:00:00', '09:00:00') dimn = (len(rng), len(rng)) exp_len = 7 - for time_index, time_col in product([True, False], [True, False]): if time_index: index = rng @@ -746,15 +745,13 @@ def test_between_time_axis(self): assert len(ts.between_time(stime, etime, axis=0)) == exp_len else: pytest.raises(TypeError, ts.between_time, stime, etime) - pytest.raises(TypeError, ts.between_time, stime, etime, - axis=0) + pytest.raises(TypeError, ts.between_time, stime, etime, axis=0) if time_col: selected = ts.between_time(stime, etime, axis=1).columns assert len(selected) == exp_len else: - pytest.raises(TypeError, ts.between_time, stime, etime, - axis=1) + pytest.raises(TypeError, ts.between_time, stime, etime, axis=1) def test_operation_on_NaT(self): # Both NaT and Timestamp are in DataFrame. From adf543d652cdcb72f3310eb3c1d8dc51a5264dab Mon Sep 17 00:00:00 2001 From: Yotam Reshef Date: Sat, 14 Jul 2018 02:00:36 +0300 Subject: [PATCH 03/10] added version/issue info for 8839 --- doc/source/whatsnew/v0.24.0.txt | 2 + pandas/core/generic.py | 5 ++ pandas/tests/frame/test_timeseries.py | 78 ++++++++++++++------------ pandas/tests/series/test_timeseries.py | 1 + 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index f26d3d76592d0..a7880cbeff0a2 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -182,6 +182,8 @@ Other Enhancements - :func:`to_timedelta` now supports iso-formated timedelta strings (:issue:`21877`) - :class:`Series` and :class:`DataFrame` now support :class:`Iterable` in constructor (:issue:`2193`) - :class:`DatetimeIndex` gained :attr:`DatetimeIndex.timetz` attribute. Returns local time with timezone information. (:issue:`21358`) +- :func:`between_time` and :func:`at_time` now support an axis parameter (:issue: `8839`) +- .. _whatsnew_0240.api_breaking: diff --git a/pandas/core/generic.py b/pandas/core/generic.py index d3c9d1472dccb..5f7245ac33546 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -7027,6 +7027,9 @@ def at_time(self, time, asof=False, axis=None): time : datetime.time or string axis : int or string axis name, optional + .. versionadded:: 0.24.0 + + Returns ------- values_at_time : same type as caller @@ -7087,6 +7090,8 @@ def between_time(self, start_time, end_time, include_start=True, include_end : boolean, default True axis : int or string axis name, optional + .. versionadded:: 0.24.0 + Returns ------- values_between_time : same type as caller diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index ebf101d60d164..341e4c0b3d4df 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -640,21 +640,26 @@ def test_at_time_raises(self): with pytest.raises(TypeError): # index is not a DatetimeIndex df.at_time('00:00') - def test_at_time_axis(self): + @pytest.mark.parametrize('time_axis', [ + (False, False), (True, False), (False, True), (True, True)]) + def test_at_time_axis(self, time_axis): + # issue 8839 rng = date_range('1/1/2000', '1/5/2000', freq='5min') ts = DataFrame(np.random.randn(len(rng), len(rng))) indices = rng[(rng.hour == 9) & (rng.minute == 30) & (rng.second == 0)] - ts.index = rng - expected = ts.loc[indices] - result = ts.at_time('9:30', axis=0) - assert_frame_equal(result, expected) + if time_axis[0]: + ts.index = rng + expected = ts.loc[indices] + result = ts.at_time('9:30', axis=0) + assert_frame_equal(result, expected) - ts.columns = rng - expected = ts.loc[:, indices] - result = ts.at_time('9:30', axis=1) - assert_frame_equal(result, expected) + if time_axis[1]: + ts.columns = rng + expected = ts.loc[:, indices] + result = ts.at_time('9:30', axis=1) + assert_frame_equal(result, expected) def test_between_time(self): rng = date_range('1/1/2000', '1/5/2000', freq='5min') @@ -722,36 +727,39 @@ def test_between_time_raises(self): with pytest.raises(TypeError): # index is not a DatetimeIndex df.between_time(start_time='00:00', end_time='12:00') - def test_between_time_axis(self): + @pytest.mark.parametrize('time_axis', [ + (False, False), (True, False), (False, True), (True, True)]) + def test_between_time_axis(self, time_axis): + # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') blank = np.arange(0, len(rng)) stime, etime = ('08:00:00', '09:00:00') - dimn = (len(rng), len(rng)) + rand_data = np.random.randn(len(rng), len(rng)) exp_len = 7 - for time_index, time_col in product([True, False], [True, False]): - if time_index: - index = rng - else: - index = blank - if time_col: - col = rng - else: - col = blank - - ts = DataFrame(np.random.randn(*dimn), index=index, columns=col) - - if time_index: - assert len(ts.between_time(stime, etime)) == exp_len - assert len(ts.between_time(stime, etime, axis=0)) == exp_len - else: - pytest.raises(TypeError, ts.between_time, stime, etime) - pytest.raises(TypeError, ts.between_time, stime, etime, axis=0) - - if time_col: - selected = ts.between_time(stime, etime, axis=1).columns - assert len(selected) == exp_len - else: - pytest.raises(TypeError, ts.between_time, stime, etime, axis=1) + + if time_axis[0]: + index = rng + else: + index = blank + if time_axis[1]: + col = rng + else: + col = blank + + ts = DataFrame(rand_data, index=index, columns=col) + + if time_axis[0]: + assert len(ts.between_time(stime, etime)) == exp_len + assert len(ts.between_time(stime, etime, axis=0)) == exp_len + else: + pytest.raises(TypeError, ts.between_time, stime, etime) + pytest.raises(TypeError, ts.between_time, stime, etime, axis=0) + + if time_axis[1]: + selected = ts.between_time(stime, etime, axis=1).columns + assert len(selected) == exp_len + else: + pytest.raises(TypeError, ts.between_time, stime, etime, axis=1) def test_operation_on_NaT(self): # Both NaT and Timestamp are in DataFrame. diff --git a/pandas/tests/series/test_timeseries.py b/pandas/tests/series/test_timeseries.py index c76c21e57bcbe..f5c365003f28e 100644 --- a/pandas/tests/series/test_timeseries.py +++ b/pandas/tests/series/test_timeseries.py @@ -826,6 +826,7 @@ def test_between_time_formats(self): assert len(ts.between_time(*time_string)) == expected_length def test_between_time_axis(self): + # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') ts = Series(np.random.randn(len(rng)), index=rng) stime, etime = ('08:00:00', '09:00:00') From bc83f9d2a8ad98c1c04a3ed0cb223d521864ef17 Mon Sep 17 00:00:00 2001 From: Yotam Reshef Date: Sat, 14 Jul 2018 02:07:46 +0300 Subject: [PATCH 04/10] whatsnew merge with master --- doc/source/whatsnew/v0.24.0.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index a7880cbeff0a2..8db32a644412f 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -182,6 +182,7 @@ Other Enhancements - :func:`to_timedelta` now supports iso-formated timedelta strings (:issue:`21877`) - :class:`Series` and :class:`DataFrame` now support :class:`Iterable` in constructor (:issue:`2193`) - :class:`DatetimeIndex` gained :attr:`DatetimeIndex.timetz` attribute. Returns local time with timezone information. (:issue:`21358`) +- :func:`~DataFrame.to_csv` and :func:`~DataFrame.to_json` now support ``compression='infer'`` to infer compression based on filename (:issue:`15008`) - :func:`between_time` and :func:`at_time` now support an axis parameter (:issue: `8839`) - From ad418718c8d6a0d5a22b331a32f0384442a1b5c8 Mon Sep 17 00:00:00 2001 From: Yotam Reshef Date: Sun, 15 Jul 2018 05:09:22 +0300 Subject: [PATCH 05/10] test_between_time parametrization simplified, raises test created --- doc/source/whatsnew/v0.24.0.txt | 2 +- pandas/core/generic.py | 10 ++-- pandas/tests/frame/test_timeseries.py | 70 +++++++++++++-------------- 3 files changed, 42 insertions(+), 40 deletions(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 8db32a644412f..186162c6be63e 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -183,7 +183,7 @@ Other Enhancements - :class:`Series` and :class:`DataFrame` now support :class:`Iterable` in constructor (:issue:`2193`) - :class:`DatetimeIndex` gained :attr:`DatetimeIndex.timetz` attribute. Returns local time with timezone information. (:issue:`21358`) - :func:`~DataFrame.to_csv` and :func:`~DataFrame.to_json` now support ``compression='infer'`` to infer compression based on filename (:issue:`15008`) -- :func:`between_time` and :func:`at_time` now support an axis parameter (:issue: `8839`) +- :func:`between_time` and :func:`at_time` now support an ``axis`` parameter (:issue: `8839`) - .. _whatsnew_0240.api_breaking: diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 5f7245ac33546..38abdde559a77 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -7062,13 +7062,14 @@ def at_time(self, time, asof=False, axis=None): axis = self._stat_axis_number axis = self._get_axis_number(axis) + index = self._get_axis(axis) try: - index = self._get_axis(axis) indexer = index.indexer_at_time(time, asof=asof) - return self._take(indexer, axis=axis) except AttributeError: raise TypeError('Index must be DatetimeIndex') + return self._take(indexer, axis=axis) + def between_time(self, start_time, end_time, include_start=True, include_end=True, axis=None): """ @@ -7132,15 +7133,16 @@ def between_time(self, start_time, end_time, include_start=True, axis = self._stat_axis_number axis = self._get_axis_number(axis) + index = self._get_axis(axis) try: - index = self._get_axis(axis) indexer = index.indexer_between_time( start_time, end_time, include_start=include_start, include_end=include_end) - return self._take(indexer, axis=axis) except AttributeError: raise TypeError('Index must be DatetimeIndex') + return self._take(indexer, axis=axis) + def resample(self, rule, how=None, axis=0, fill_method=None, closed=None, label=None, convention='start', kind=None, loffset=None, limit=None, base=0, on=None, level=None): diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index 341e4c0b3d4df..0e83115239bb3 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -640,26 +640,22 @@ def test_at_time_raises(self): with pytest.raises(TypeError): # index is not a DatetimeIndex df.at_time('00:00') - @pytest.mark.parametrize('time_axis', [ - (False, False), (True, False), (False, True), (True, True)]) - def test_at_time_axis(self, time_axis): + @pytest.mark.parametrize('axis', ['index', 'columns']) + def test_at_time_axis(self, axis): # issue 8839 rng = date_range('1/1/2000', '1/5/2000', freq='5min') ts = DataFrame(np.random.randn(len(rng), len(rng))) + ts.index, ts.columns = rng, rng indices = rng[(rng.hour == 9) & (rng.minute == 30) & (rng.second == 0)] - if time_axis[0]: - ts.index = rng - expected = ts.loc[indices] - result = ts.at_time('9:30', axis=0) - assert_frame_equal(result, expected) - - if time_axis[1]: - ts.columns = rng + if axis == 'index': + expected = ts.loc[indices, :] + elif axis == 'columns': expected = ts.loc[:, indices] - result = ts.at_time('9:30', axis=1) - assert_frame_equal(result, expected) + + result = ts.at_time('9:30', axis=axis) + assert_frame_equal(result, expected) def test_between_time(self): rng = date_range('1/1/2000', '1/5/2000', freq='5min') @@ -727,38 +723,42 @@ def test_between_time_raises(self): with pytest.raises(TypeError): # index is not a DatetimeIndex df.between_time(start_time='00:00', end_time='12:00') - @pytest.mark.parametrize('time_axis', [ - (False, False), (True, False), (False, True), (True, True)]) - def test_between_time_axis(self, time_axis): + @pytest.mark.parametrize('axis', [ + (), 'index', 'columns', ('index', 'columns')]) + def test_between_time_axis(self, axis): # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') - blank = np.arange(0, len(rng)) + ts = DataFrame(np.random.randn(len(rng), len(rng))) stime, etime = ('08:00:00', '09:00:00') - rand_data = np.random.randn(len(rng), len(rng)) exp_len = 7 - if time_axis[0]: - index = rng - else: - index = blank - if time_axis[1]: - col = rng - else: - col = blank - - ts = DataFrame(rand_data, index=index, columns=col) - - if time_axis[0]: + if 'index' in axis: + ts.index = rng assert len(ts.between_time(stime, etime)) == exp_len assert len(ts.between_time(stime, etime, axis=0)) == exp_len - else: - pytest.raises(TypeError, ts.between_time, stime, etime) - pytest.raises(TypeError, ts.between_time, stime, etime, axis=0) - if time_axis[1]: + if 'columns' in axis: + ts.columns = rng selected = ts.between_time(stime, etime, axis=1).columns assert len(selected) == exp_len - else: + + @pytest.mark.parametrize('axis', [ + (), 'index', 'columns', ('index', 'columns')]) + def test_between_time_axis_raises(self, axis): + # issue 8839 + rng = date_range('1/1/2000', periods=100, freq='10min') + mask = np.arange(0, len(rng)) + rand_data = np.random.randn(len(rng), len(rng)) + ts = DataFrame(rand_data, index=rng, columns=rng) + stime, etime = ('08:00:00', '09:00:00') + + if 'index' not in axis: + ts.index = mask + pytest.raises(TypeError, ts.between_time, stime, etime) + pytest.raises(TypeError, ts.between_time, stime, etime, axis=0) + + if 'columns' not in axis: + ts.columns = mask pytest.raises(TypeError, ts.between_time, stime, etime, axis=1) def test_operation_on_NaT(self): From 5ea87f4ac998172bb73b665795006667a6e5080f Mon Sep 17 00:00:00 2001 From: Yotam Reshef Date: Fri, 3 Aug 2018 14:44:26 +0300 Subject: [PATCH 06/10] 0, 1 axes added to tests --- pandas/tests/frame/test_timeseries.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index 0e83115239bb3..e649b9d2de498 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -640,7 +640,7 @@ def test_at_time_raises(self): with pytest.raises(TypeError): # index is not a DatetimeIndex df.at_time('00:00') - @pytest.mark.parametrize('axis', ['index', 'columns']) + @pytest.mark.parametrize('axis', ['index', 'columns', 0, 1]) def test_at_time_axis(self, axis): # issue 8839 rng = date_range('1/1/2000', '1/5/2000', freq='5min') @@ -649,9 +649,9 @@ def test_at_time_axis(self, axis): indices = rng[(rng.hour == 9) & (rng.minute == 30) & (rng.second == 0)] - if axis == 'index': + if axis in ['index', 0]: expected = ts.loc[indices, :] - elif axis == 'columns': + elif axis in ['columns', 1]: expected = ts.loc[:, indices] result = ts.at_time('9:30', axis=axis) @@ -724,7 +724,7 @@ def test_between_time_raises(self): df.between_time(start_time='00:00', end_time='12:00') @pytest.mark.parametrize('axis', [ - (), 'index', 'columns', ('index', 'columns')]) + (), 'index', 'columns', ('index', 'columns'), 0, 1, (0,1)]) def test_between_time_axis(self, axis): # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') @@ -732,12 +732,12 @@ def test_between_time_axis(self, axis): stime, etime = ('08:00:00', '09:00:00') exp_len = 7 - if 'index' in axis: + if 'index' in axis or 0 in axis: ts.index = rng assert len(ts.between_time(stime, etime)) == exp_len assert len(ts.between_time(stime, etime, axis=0)) == exp_len - if 'columns' in axis: + if 'columns' in axis or 1 in axis: ts.columns = rng selected = ts.between_time(stime, etime, axis=1).columns assert len(selected) == exp_len From 4ab35ee2bd2be73fa7ae1a1f1909533488d36d01 Mon Sep 17 00:00:00 2001 From: Yotam Reshef Date: Fri, 3 Aug 2018 15:10:40 +0300 Subject: [PATCH 07/10] test_between_time_axis uses tuples --- pandas/tests/frame/test_timeseries.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index e649b9d2de498..7dc94a1d093e6 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -724,7 +724,7 @@ def test_between_time_raises(self): df.between_time(start_time='00:00', end_time='12:00') @pytest.mark.parametrize('axis', [ - (), 'index', 'columns', ('index', 'columns'), 0, 1, (0,1)]) + (), ('index',), ('columns',), ('index', 'columns'), (0,), (1,), (0,1)]) def test_between_time_axis(self, axis): # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') @@ -743,7 +743,7 @@ def test_between_time_axis(self, axis): assert len(selected) == exp_len @pytest.mark.parametrize('axis', [ - (), 'index', 'columns', ('index', 'columns')]) + (), ('index',), ('columns',), ('index', 'columns'), (0,), (1,), (0,1)]) def test_between_time_axis_raises(self, axis): # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') @@ -752,12 +752,12 @@ def test_between_time_axis_raises(self, axis): ts = DataFrame(rand_data, index=rng, columns=rng) stime, etime = ('08:00:00', '09:00:00') - if 'index' not in axis: + if 'index' not in axis and 0 not in axis: ts.index = mask pytest.raises(TypeError, ts.between_time, stime, etime) pytest.raises(TypeError, ts.between_time, stime, etime, axis=0) - if 'columns' not in axis: + if 'columns' not in axis and 1 not in axis: ts.columns = mask pytest.raises(TypeError, ts.between_time, stime, etime, axis=1) From 35b4b41471a3d9f6f1bdcd518251cb0a9efd333d Mon Sep 17 00:00:00 2001 From: Yotam Reshef Date: Thu, 9 Aug 2018 16:26:45 +0300 Subject: [PATCH 08/10] flake8 fixes --- pandas/tests/frame/test_timeseries.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index 7dc94a1d093e6..9dba83ec6ac87 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -724,7 +724,8 @@ def test_between_time_raises(self): df.between_time(start_time='00:00', end_time='12:00') @pytest.mark.parametrize('axis', [ - (), ('index',), ('columns',), ('index', 'columns'), (0,), (1,), (0,1)]) + (), ('index',), ('columns',), ('index', 'columns'), + (0, ), (1, ), (0, 1)]) def test_between_time_axis(self, axis): # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') @@ -743,7 +744,8 @@ def test_between_time_axis(self, axis): assert len(selected) == exp_len @pytest.mark.parametrize('axis', [ - (), ('index',), ('columns',), ('index', 'columns'), (0,), (1,), (0,1)]) + (), ('index',), ('columns',), ('index', 'columns'), + (0, ), (1, ), (0, 1)]) def test_between_time_axis_raises(self, axis): # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') From 3a9550e444ca467239b11e8b69f2c0bd4c7a4c93 Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Sun, 18 Nov 2018 13:53:37 -0500 Subject: [PATCH 09/10] use axis fixture --- pandas/tests/frame/test_timeseries.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index 259b3d9291349..89a117f0c14ca 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -721,9 +721,6 @@ def test_between_time_raises(self): with pytest.raises(TypeError): # index is not a DatetimeIndex df.between_time(start_time='00:00', end_time='12:00') - @pytest.mark.parametrize('axis', [ - (), ('index',), ('columns',), ('index', 'columns'), - (0, ), (1, ), (0, 1)]) def test_between_time_axis(self, axis): # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') @@ -731,19 +728,16 @@ def test_between_time_axis(self, axis): stime, etime = ('08:00:00', '09:00:00') exp_len = 7 - if 'index' in axis or 0 in axis: + if axis in ['index', 0]: ts.index = rng assert len(ts.between_time(stime, etime)) == exp_len assert len(ts.between_time(stime, etime, axis=0)) == exp_len - if 'columns' in axis or 1 in axis: + if axis in ['columns', 1]: ts.columns = rng selected = ts.between_time(stime, etime, axis=1).columns assert len(selected) == exp_len - @pytest.mark.parametrize('axis', [ - (), ('index',), ('columns',), ('index', 'columns'), - (0, ), (1, ), (0, 1)]) def test_between_time_axis_raises(self, axis): # issue 8839 rng = date_range('1/1/2000', periods=100, freq='10min') @@ -752,12 +746,12 @@ def test_between_time_axis_raises(self, axis): ts = DataFrame(rand_data, index=rng, columns=rng) stime, etime = ('08:00:00', '09:00:00') - if 'index' not in axis and 0 not in axis: + if axis in ['columns', 1]: ts.index = mask pytest.raises(TypeError, ts.between_time, stime, etime) pytest.raises(TypeError, ts.between_time, stime, etime, axis=0) - if 'columns' not in axis and 1 not in axis: + if axis in ['index', 0]: ts.columns = mask pytest.raises(TypeError, ts.between_time, stime, etime, axis=1) From 9ae360fe142dcb6d0e50e61d171de00ddaff0581 Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Sun, 18 Nov 2018 16:50:26 -0500 Subject: [PATCH 10/10] parameterize --- pandas/core/generic.py | 4 +- pandas/tests/frame/test_timeseries.py | 90 ++++++++++++++------------- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 83ca46271c21a..dde671993a56b 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -7393,7 +7393,7 @@ def at_time(self, time, asof=False, axis=None): Parameters ---------- time : datetime.time or string - axis : int or string axis name, optional + axis : {0 or 'index', 1 or 'columns'}, default 0 .. versionadded:: 0.24.0 @@ -7457,7 +7457,7 @@ def between_time(self, start_time, end_time, include_start=True, end_time : datetime.time or string include_start : boolean, default True include_end : boolean, default True - axis : int or string axis name, optional + axis : {0 or 'index', 1 or 'columns'}, default 0 .. versionadded:: 0.24.0 diff --git a/pandas/tests/frame/test_timeseries.py b/pandas/tests/frame/test_timeseries.py index 89a117f0c14ca..52f0b30bf0f0c 100644 --- a/pandas/tests/frame/test_timeseries.py +++ b/pandas/tests/frame/test_timeseries.py @@ -25,6 +25,11 @@ from pandas.tests.frame.common import TestData +@pytest.fixture(params=product([True, False], [True, False])) +def close_open_fixture(request): + return request.param + + class TestDataFrameTimeSeriesMethods(TestData): def test_diff(self): @@ -655,33 +660,32 @@ def test_at_time_axis(self, axis): result = ts.at_time('9:30', axis=axis) assert_frame_equal(result, expected) - def test_between_time(self): + def test_between_time(self, close_open_fixture): rng = date_range('1/1/2000', '1/5/2000', freq='5min') ts = DataFrame(np.random.randn(len(rng), 2), index=rng) stime = time(0, 0) etime = time(1, 0) - - close_open = product([True, False], [True, False]) - for inc_start, inc_end in close_open: - filtered = ts.between_time(stime, etime, inc_start, inc_end) - exp_len = 13 * 4 + 1 - if not inc_start: - exp_len -= 5 - if not inc_end: - exp_len -= 4 - - assert len(filtered) == exp_len - for rs in filtered.index: - t = rs.time() - if inc_start: - assert t >= stime - else: - assert t > stime - - if inc_end: - assert t <= etime - else: - assert t < etime + inc_start, inc_end = close_open_fixture + + filtered = ts.between_time(stime, etime, inc_start, inc_end) + exp_len = 13 * 4 + 1 + if not inc_start: + exp_len -= 5 + if not inc_end: + exp_len -= 4 + + assert len(filtered) == exp_len + for rs in filtered.index: + t = rs.time() + if inc_start: + assert t >= stime + else: + assert t > stime + + if inc_end: + assert t <= etime + else: + assert t < etime result = ts.between_time('00:00', '01:00') expected = ts.between_time(stime, etime) @@ -693,27 +697,25 @@ def test_between_time(self): stime = time(22, 0) etime = time(9, 0) - close_open = product([True, False], [True, False]) - for inc_start, inc_end in close_open: - filtered = ts.between_time(stime, etime, inc_start, inc_end) - exp_len = (12 * 11 + 1) * 4 + 1 - if not inc_start: - exp_len -= 4 - if not inc_end: - exp_len -= 4 - - assert len(filtered) == exp_len - for rs in filtered.index: - t = rs.time() - if inc_start: - assert (t >= stime) or (t <= etime) - else: - assert (t > stime) or (t <= etime) - - if inc_end: - assert (t <= etime) or (t >= stime) - else: - assert (t < etime) or (t >= stime) + filtered = ts.between_time(stime, etime, inc_start, inc_end) + exp_len = (12 * 11 + 1) * 4 + 1 + if not inc_start: + exp_len -= 4 + if not inc_end: + exp_len -= 4 + + assert len(filtered) == exp_len + for rs in filtered.index: + t = rs.time() + if inc_start: + assert (t >= stime) or (t <= etime) + else: + assert (t > stime) or (t <= etime) + + if inc_end: + assert (t <= etime) or (t >= stime) + else: + assert (t < etime) or (t >= stime) def test_between_time_raises(self): # GH20725