From 61f1a93b6c2f683f6353ea1411d505f98865631a Mon Sep 17 00:00:00 2001 From: phofl Date: Sun, 13 Dec 2020 14:34:15 +0100 Subject: [PATCH 1/4] Fix offset for n greater one --- pandas/core/generic.py | 5 +++-- pandas/tests/frame/methods/test_first_and_last.py | 9 +++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index cb4f103ce1c8d..88715426741d7 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -8421,8 +8421,9 @@ def first(self: FrameOrSeries, offset) -> FrameOrSeries: offset = to_offset(offset) if not isinstance(offset, Tick) and offset.is_on_offset(self.index[0]): - # GH#29623 if first value is end of period - end_date = end = self.index[0] + # GH#29623 if first value is end of period, remove offset with n = 1 + # before adding the real offset + end_date = end = self.index[0] - to_offset(offset.name) + offset else: end_date = end = self.index[0] + offset diff --git a/pandas/tests/frame/methods/test_first_and_last.py b/pandas/tests/frame/methods/test_first_and_last.py index 4ee7016004137..43469a093f827 100644 --- a/pandas/tests/frame/methods/test_first_and_last.py +++ b/pandas/tests/frame/methods/test_first_and_last.py @@ -79,3 +79,12 @@ def test_first_with_first_day_last_of_month(self, frame_or_series, start, period [1] * periods, index=bdate_range(start, periods=periods) ) tm.assert_equal(result, expected) + + def test_first_with_first_day_end_of_frq_n_greater_one(self, frame_or_series): + # GH#29623 + x = frame_or_series([1] * 100, index=bdate_range("2010-03-31", periods=100)) + result = x.first("2M") + expected = frame_or_series( + [1] * 23, index=bdate_range("2010-03-31", "2010-04-30") + ) + tm.assert_equal(result, expected) From e02eca2f5dc926cc132adc1598fc757f4bca3b94 Mon Sep 17 00:00:00 2001 From: phofl Date: Sun, 13 Dec 2020 16:59:50 +0100 Subject: [PATCH 2/4] Merge commit --- doc/source/whatsnew/v1.2.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index bc7f5b8174573..ac7ef462cdea6 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -607,6 +607,7 @@ Datetimelike - Bug in :meth:`Series.isin` with ``datetime64[ns]`` dtype and :meth:`.DatetimeIndex.isin` failing to consider timezone-aware and timezone-naive datetimes as always different (:issue:`35728`) - Bug in :meth:`Series.isin` with ``PeriodDtype`` dtype and :meth:`PeriodIndex.isin` failing to consider arguments with different ``PeriodDtype`` as always different (:issue:`37528`) - Bug in :class:`Period` constructor now correctly handles nanoseconds in the ``value`` argument (:issue:`34621` and :issue:`17053`) +- Bug in :meth:`DataFrame.first` and :meth:`Series.first` returning two months for offset one month when first day is last calendar day (:issue:`29623`) Timedelta ^^^^^^^^^ From c618863b7c1701245c778313ad3ac21a6c290108 Mon Sep 17 00:00:00 2001 From: phofl Date: Sun, 13 Dec 2020 18:08:36 +0100 Subject: [PATCH 3/4] Move whatsnew --- doc/source/whatsnew/v1.2.0.rst | 1 - doc/source/whatsnew/v1.3.0.rst | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index ac7ef462cdea6..bc7f5b8174573 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -607,7 +607,6 @@ Datetimelike - Bug in :meth:`Series.isin` with ``datetime64[ns]`` dtype and :meth:`.DatetimeIndex.isin` failing to consider timezone-aware and timezone-naive datetimes as always different (:issue:`35728`) - Bug in :meth:`Series.isin` with ``PeriodDtype`` dtype and :meth:`PeriodIndex.isin` failing to consider arguments with different ``PeriodDtype`` as always different (:issue:`37528`) - Bug in :class:`Period` constructor now correctly handles nanoseconds in the ``value`` argument (:issue:`34621` and :issue:`17053`) -- Bug in :meth:`DataFrame.first` and :meth:`Series.first` returning two months for offset one month when first day is last calendar day (:issue:`29623`) Timedelta ^^^^^^^^^ diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index d86c1b7911528..4202c01dfe551 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -156,7 +156,7 @@ Categorical Datetimelike ^^^^^^^^^^^^ - Bug in :class:`DataFrame` and :class:`Series` constructors sometimes dropping nanoseconds from :class:`Timestamp` (resp. :class:`Timedelta`) ``data``, with ``dtype=datetime64[ns]`` (resp. ``timedelta64[ns]``) (:issue:`38032`) -- +- Bug in :meth:`DataFrame.first` and :meth:`Series.first` returning two months for offset one month when first day is last calendar day (:issue:`29623`) - Timedelta From 9469ea73bb7b7d263d5e60a092e2185a3ab65b87 Mon Sep 17 00:00:00 2001 From: phofl Date: Sat, 19 Dec 2020 00:07:50 +0100 Subject: [PATCH 4/4] Add offset.base --- pandas/core/generic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 88715426741d7..e0b5df7e2cf0c 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -8423,7 +8423,7 @@ def first(self: FrameOrSeries, offset) -> FrameOrSeries: if not isinstance(offset, Tick) and offset.is_on_offset(self.index[0]): # GH#29623 if first value is end of period, remove offset with n = 1 # before adding the real offset - end_date = end = self.index[0] - to_offset(offset.name) + offset + end_date = end = self.index[0] - offset.base + offset else: end_date = end = self.index[0] + offset