From c1645fcf9aee205d562a5c4cb442ff85a987c24c Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Thu, 24 Sep 2020 10:11:25 +0100 Subject: [PATCH 1/9] Revert "ENH: infer freq in timedelta_range (#32377)" This reverts commit d219c2c63d29b3affbc0e67d7c3dbfb6946b54de. --- pandas/_testing.py | 4 ++-- pandas/core/arrays/timedeltas.py | 8 -------- pandas/tests/indexes/timedeltas/test_timedelta_range.py | 1 - 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/pandas/_testing.py b/pandas/_testing.py index 3e3ba480ebfeb..6c0e311ab6c92 100644 --- a/pandas/_testing.py +++ b/pandas/_testing.py @@ -841,9 +841,9 @@ def repr_class(x): raise_assert_detail(obj, msg, repr_class(left), repr_class(right)) -def assert_attr_equal(attr: str, left, right, obj: str = "Attributes"): +def assert_attr_equal(attr, left, right, obj="Attributes"): """ - Check attributes are equal. Both objects must have attribute. + checks attributes are equal. Both objects must have attribute. Parameters ---------- diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 3eaf428bc64b2..320983222a769 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -264,10 +264,6 @@ def _generate_range(cls, start, end, periods, freq, closed=None): index = generate_regular_range(start, end, periods, freq) else: index = np.linspace(start.value, end.value, periods).astype("i8") - if len(index) >= 2: - # Infer a frequency - td = Timedelta(index[1] - index[0]) - freq = to_offset(td) if not left_closed: index = index[1:] @@ -620,10 +616,6 @@ def __floordiv__(self, other): if self.freq is not None: # Note: freq gets division, not floor-division freq = self.freq / other - if freq.nanos == 0 and self.freq.nanos != 0: - # e.g. if self.freq is Nano(1) then dividing by 2 - # rounds down to zero - freq = None return type(self)(result.view("m8[ns]"), freq=freq) if not hasattr(other, "dtype"): diff --git a/pandas/tests/indexes/timedeltas/test_timedelta_range.py b/pandas/tests/indexes/timedeltas/test_timedelta_range.py index 7d78fbf9ff190..ceb5e562a4539 100644 --- a/pandas/tests/indexes/timedeltas/test_timedelta_range.py +++ b/pandas/tests/indexes/timedeltas/test_timedelta_range.py @@ -38,7 +38,6 @@ def test_linspace_behavior(self, periods, freq): result = timedelta_range(start="0 days", end="4 days", periods=periods) expected = timedelta_range(start="0 days", end="4 days", freq=freq) tm.assert_index_equal(result, expected) - assert result.freq == freq def test_errors(self): # not enough params From 24de61390f571dc68f10578c5cc5a91ffe40655c Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Thu, 24 Sep 2020 10:12:48 +0100 Subject: [PATCH 2/9] re-instate unrelated change --- pandas/_testing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/_testing.py b/pandas/_testing.py index 6c0e311ab6c92..3e3ba480ebfeb 100644 --- a/pandas/_testing.py +++ b/pandas/_testing.py @@ -841,9 +841,9 @@ def repr_class(x): raise_assert_detail(obj, msg, repr_class(left), repr_class(right)) -def assert_attr_equal(attr, left, right, obj="Attributes"): +def assert_attr_equal(attr: str, left, right, obj: str = "Attributes"): """ - checks attributes are equal. Both objects must have attribute. + Check attributes are equal. Both objects must have attribute. Parameters ---------- From 6b89190f7a141c0d4d29bfbba564576c40bdd8c1 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Thu, 24 Sep 2020 10:32:36 +0100 Subject: [PATCH 3/9] add tests --- pandas/tests/arithmetic/test_timedelta64.py | 5 +++++ pandas/tests/indexes/timedeltas/test_timedelta_range.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 64d3d5b6d684d..069feb29a5143 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -2136,3 +2136,8 @@ def test_td64arr_pow_invalid(self, scalar_td, box_with_array): with pytest.raises(TypeError, match=pattern): td1 ** scalar_td + + def test_add_timestamp_to_timedelta(self): + # https://github.com/pandas-dev/pandas/issues/35897 + result = Timestamp.now() + timedelta_range("0s", "1s", periods=31) + assert result.freq is None diff --git a/pandas/tests/indexes/timedeltas/test_timedelta_range.py b/pandas/tests/indexes/timedeltas/test_timedelta_range.py index ceb5e562a4539..dc3df4427f351 100644 --- a/pandas/tests/indexes/timedeltas/test_timedelta_range.py +++ b/pandas/tests/indexes/timedeltas/test_timedelta_range.py @@ -78,3 +78,8 @@ def test_timedelta_range_freq_divide_end(self, start, end, freq, expected_period assert Timedelta(start) == res[0] assert Timedelta(end) >= res[-1] assert len(res) == expected_periods + + def test_timedelta_range_infer_freq(self): + # https://github.com/pandas-dev/pandas/issues/35897 + result = timedelta_range("0s", "1s", periods=31) + assert result.freq is None From a624f9a83248d36d9bd7d4345e5b9039f1413419 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Thu, 24 Sep 2020 11:09:05 +0100 Subject: [PATCH 4/9] fix failing doctest --- pandas/core/indexes/timedeltas.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index df08fda78823d..20ebc80c7e0af 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -328,8 +328,8 @@ def timedelta_range( >>> pd.timedelta_range(start='1 day', end='5 days', periods=4) TimedeltaIndex(['1 days 00:00:00', '2 days 08:00:00', '3 days 16:00:00', - '5 days 00:00:00'], - dtype='timedelta64[ns]', freq='32H') + '5 days 00:00:00'], + dtype='timedelta64[ns]', freq=None) """ if freq is None and com.any_none(periods, start, end): freq = "D" From 2faea7f9322782beb7eb9f8b3a73fb89ff110787 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Fri, 25 Sep 2020 11:19:51 +0100 Subject: [PATCH 5/9] release note from #36582 --- doc/source/whatsnew/v1.1.3.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.1.3.rst b/doc/source/whatsnew/v1.1.3.rst index c63a78c76572f..058706d20c745 100644 --- a/doc/source/whatsnew/v1.1.3.rst +++ b/doc/source/whatsnew/v1.1.3.rst @@ -31,6 +31,7 @@ Fixed regressions ~~~~~~~~~~~~~~~~~ - Fixed regression in :meth:`DataFrame.agg`, :meth:`DataFrame.apply`, :meth:`Series.agg`, and :meth:`Series.apply` where internal suffix is exposed to the users when no relabelling is applied (:issue:`36189`) - Fixed regression in :class:`IntegerArray` unary plus and minus operations raising a ``TypeError`` (:issue:`36063`) +- Fixed regression when adding a :meth:`timedelta_range` to a :class:``Timestamp`` raised an ``ValueError`` (:issue:`35897`) - Fixed regression in :meth:`Series.__getitem__` incorrectly raising when the input was a tuple (:issue:`35534`) - Fixed regression in :meth:`Series.__getitem__` incorrectly raising when the input was a frozenset (:issue:`35747`) - Fixed regression in :meth:`read_excel` with ``engine="odf"`` caused ``UnboundLocalError`` in some cases where cells had nested child nodes (:issue:`36122`, :issue:`35802`) From 9d38060f5df9f5cb405b77f99a55f9c350162dd6 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Fri, 25 Sep 2020 11:30:46 +0100 Subject: [PATCH 6/9] copy test from #36582 --- pandas/tests/arithmetic/test_timedelta64.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 069feb29a5143..7ff51c8b2144b 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -2137,7 +2137,19 @@ def test_td64arr_pow_invalid(self, scalar_td, box_with_array): with pytest.raises(TypeError, match=pattern): td1 ** scalar_td - def test_add_timestamp_to_timedelta(self): - # https://github.com/pandas-dev/pandas/issues/35897 - result = Timestamp.now() + timedelta_range("0s", "1s", periods=31) - assert result.freq is None + +def test_add_timestamp_to_timedelta(): + # GH: 35897 + timestamp = pd.Timestamp.now() + result = timestamp + pd.timedelta_range("0s", "1s", periods=31) + expected = pd.DatetimeIndex( + [ + timestamp + + ( + pd.to_timedelta("0.033333333s") * i + + pd.to_timedelta("0.000000001s") * divmod(i, 3)[0] + ) + for i in range(31) + ] + ) + tm.assert_index_equal(result, expected) \ No newline at end of file From 46ee97f6d3cda89d59583b83fabfecf6df38eb03 Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Fri, 25 Sep 2020 11:37:09 +0100 Subject: [PATCH 7/9] added additional release note --- doc/source/whatsnew/v1.1.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.1.3.rst b/doc/source/whatsnew/v1.1.3.rst index 058706d20c745..6f834aa7e3836 100644 --- a/doc/source/whatsnew/v1.1.3.rst +++ b/doc/source/whatsnew/v1.1.3.rst @@ -61,7 +61,7 @@ Bug fixes Other ~~~~~ -- +- Reverted enhancement added in pandas-1.1.0 where :func:`timedelta_range` infers a frequency when passed ``start``, ``stop``, and ``periods`` (:issue:`32377`) .. --------------------------------------------------------------------------- From 0b8eaf005d38a3c7ed5682e35a12be02faa5917c Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Fri, 25 Sep 2020 11:39:08 +0100 Subject: [PATCH 8/9] lint --- pandas/tests/arithmetic/test_timedelta64.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 7ff51c8b2144b..dd9b6269ce5bf 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -2152,4 +2152,4 @@ def test_add_timestamp_to_timedelta(): for i in range(31) ] ) - tm.assert_index_equal(result, expected) \ No newline at end of file + tm.assert_index_equal(result, expected) From 9fe91aeca054840ff27261bb19e6369c5fa45ffb Mon Sep 17 00:00:00 2001 From: Simon Hawkins Date: Fri, 25 Sep 2020 19:35:54 +0100 Subject: [PATCH 9/9] re-instate nanos check --- pandas/core/arrays/timedeltas.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 320983222a769..f6f7e8290489e 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -616,6 +616,10 @@ def __floordiv__(self, other): if self.freq is not None: # Note: freq gets division, not floor-division freq = self.freq / other + if freq.nanos == 0 and self.freq.nanos != 0: + # e.g. if self.freq is Nano(1) then dividing by 2 + # rounds down to zero + freq = None return type(self)(result.view("m8[ns]"), freq=freq) if not hasattr(other, "dtype"):