Skip to content

Commit d5cddbd

Browse files
authored
[BUG]: Rolling selected too large windows with PeriodIndex (#36730)
1 parent 459aca9 commit d5cddbd

File tree

3 files changed

+43
-2
lines changed

3 files changed

+43
-2
lines changed

doc/source/whatsnew/v1.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ Groupby/resample/rolling
409409
- Bug in :meth:`DataFrameGroupBy.apply` raising error with ``np.nan`` group(s) when ``dropna=False`` (:issue:`35889`)
410410
- Bug in :meth:`Rolling.sum()` returned wrong values when dtypes where mixed between float and integer and axis was equal to one (:issue:`20649`, :issue:`35596`)
411411
- Bug in :meth:`Rolling.count` returned ``np.nan`` with :class:`pandas.api.indexers.FixedForwardWindowIndexer` as window, ``min_periods=0`` and only missing values in window (:issue:`35579`)
412+
- Bug where :class:`pandas.core.window.Rolling` produces incorrect window sizes when using a ``PeriodIndex`` (:issue:`34225`)
412413

413414
Reshaping
414415
^^^^^^^^^

pandas/core/window/rolling.py

+11-2
Original file line numberDiff line numberDiff line change
@@ -1932,7 +1932,6 @@ def validate(self):
19321932
):
19331933

19341934
self._validate_monotonic()
1935-
freq = self._validate_freq()
19361935

19371936
# we don't allow center
19381937
if self.center:
@@ -1943,7 +1942,7 @@ def validate(self):
19431942

19441943
# this will raise ValueError on non-fixed freqs
19451944
self.win_freq = self.window
1946-
self.window = freq.nanos
1945+
self.window = self._determine_window_length()
19471946
self.win_type = "freq"
19481947

19491948
# min_periods must be an integer
@@ -1963,6 +1962,16 @@ def validate(self):
19631962
"closed only implemented for datetimelike and offset based windows"
19641963
)
19651964

1965+
def _determine_window_length(self) -> Union[int, float]:
1966+
"""
1967+
Calculate freq for PeriodIndexes based on Index freq. Can not use
1968+
nanos, because asi8 of PeriodIndex is not in nanos
1969+
"""
1970+
freq = self._validate_freq()
1971+
if isinstance(self._on, ABCPeriodIndex):
1972+
return freq.nanos / (self._on.freq.nanos / self._on.freq.n)
1973+
return freq.nanos
1974+
19661975
def _validate_monotonic(self):
19671976
"""
19681977
Validate monotonic (increasing or decreasing).

pandas/tests/window/test_rolling.py

+31
Original file line numberDiff line numberDiff line change
@@ -837,3 +837,34 @@ def test_rolling_on_df_transposed():
837837

838838
result = df.T.rolling(min_periods=1, window=2).sum().T
839839
tm.assert_frame_equal(result, expected)
840+
841+
842+
@pytest.mark.parametrize(
843+
("index", "window"),
844+
[
845+
(
846+
pd.period_range(start="2020-01-01 08:00", end="2020-01-01 08:08", freq="T"),
847+
"2T",
848+
),
849+
(
850+
pd.period_range(
851+
start="2020-01-01 08:00", end="2020-01-01 12:00", freq="30T"
852+
),
853+
"1h",
854+
),
855+
],
856+
)
857+
@pytest.mark.parametrize(
858+
("func", "values"),
859+
[
860+
("min", [np.nan, 0, 0, 1, 2, 3, 4, 5, 6]),
861+
("max", [np.nan, 0, 1, 2, 3, 4, 5, 6, 7]),
862+
("sum", [np.nan, 0, 1, 3, 5, 7, 9, 11, 13]),
863+
],
864+
)
865+
def test_rolling_period_index(index, window, func, values):
866+
# GH: 34225
867+
ds = pd.Series([0, 1, 2, 3, 4, 5, 6, 7, 8], index=index)
868+
result = getattr(ds.rolling(window, closed="left"), func)()
869+
expected = pd.Series(values, index=index)
870+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)