From 658fc1f517bfd1d335b9e031621a3d08ae77b3c5 Mon Sep 17 00:00:00 2001 From: Bert Palm Date: Tue, 12 Oct 2021 17:24:17 +0200 Subject: [PATCH 1/2] [FIX] for rolling with uneven nanoseconds have wrong results --- doc/source/whatsnew/v1.4.0.rst | 1 + pandas/_libs/window/indexers.pyx | 7 +++++++ pandas/tests/window/test_rolling.py | 17 +++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index a3dc95781ee93..0495280ac7ba0 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -505,6 +505,7 @@ Groupby/resample/rolling - Bug in :meth:`GroupBy.apply` with time-based :class:`Grouper` objects incorrectly raising ``ValueError`` in corner cases where the grouping vector contains a ``NaT`` (:issue:`43500`, :issue:`43515`) - Bug in :meth:`GroupBy.mean` failing with ``complex`` dtype (:issue:`43701`) - Fixed bug in :meth:`Series.rolling` and :meth:`DataFrame.rolling` not calculating window bounds correctly for the first row when ``center=True`` and index is decreasing (:issue:`43927`) +- Fixed bug in :meth:`Series.rolling` and :meth:`DataFrame.rolling` for centered datetimelike windows with uneven nanosecond (:issue:`43997`) Reshaping ^^^^^^^^^ diff --git a/pandas/_libs/window/indexers.pyx b/pandas/_libs/window/indexers.pyx index 3782b55bd19b3..64cb8bbdcf501 100644 --- a/pandas/_libs/window/indexers.pyx +++ b/pandas/_libs/window/indexers.pyx @@ -62,6 +62,13 @@ def calculate_variable_window_bounds( if closed in ['left', 'both']: left_closed = True + # If the forward and the backward facing windows + # would result in a fraction of 1/2 a nanosecond + # we need to make both interval ends inclusive. + if center and window_size % 2 == 1: + right_closed = True + left_closed = True + if index[num_values - 1] < index[0]: index_growth_sign = -1 diff --git a/pandas/tests/window/test_rolling.py b/pandas/tests/window/test_rolling.py index d88ce2ccb54cc..a0bf07156a65f 100644 --- a/pandas/tests/window/test_rolling.py +++ b/pandas/tests/window/test_rolling.py @@ -1243,6 +1243,23 @@ def test_rolling_decreasing_indices_centered(window, closed, expected, frame_or_ tm.assert_equal(result_dec, expected_dec) +@pytest.mark.parametrize( + "window,expected", + [ + ("1ns", [1.0, 1.0, 1.0, 1.0]), + ("3ns", [2.0, 3.0, 3.0, 2.0]), + ], +) +def test_rolling_center_nanosecond_resolution( + window, closed, expected, frame_or_series +): + index = date_range("2020", periods=4, freq="1ns") + df = frame_or_series([1, 1, 1, 1], index=index, dtype=float) + expected = frame_or_series(expected, index=index, dtype=float) + result = df.rolling(window, closed=closed, center=True).sum() + tm.assert_equal(result, expected) + + @pytest.mark.parametrize( "method,expected", [ From b6a6510065c3057f55f9636e456cdf646a42e976 Mon Sep 17 00:00:00 2001 From: rosagold Date: Wed, 13 Oct 2021 12:25:35 +0200 Subject: [PATCH 2/2] Update indexers.pyx added issue number in comment --- pandas/_libs/window/indexers.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/_libs/window/indexers.pyx b/pandas/_libs/window/indexers.pyx index 7d7342538a8d4..4b3a858ade773 100644 --- a/pandas/_libs/window/indexers.pyx +++ b/pandas/_libs/window/indexers.pyx @@ -62,6 +62,7 @@ def calculate_variable_window_bounds( if closed in ['left', 'both']: left_closed = True + # GH 43997: # If the forward and the backward facing windows # would result in a fraction of 1/2 a nanosecond # we need to make both interval ends inclusive.