diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index 5213120b33f06..bcd1abba30a67 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1808,6 +1808,7 @@ Plotting Groupby/Resample/Rolling ^^^^^^^^^^^^^^^^^^^^^^^^ +- Bug in :func:`pandas.core.window.Rolling.min` and :func:`pandas.core.window.Rolling.max` with ``closed='left'``, a datetime-like index and only one entry in the series leading to segfault (:issue:`24718`) - Bug in :func:`pandas.core.groupby.GroupBy.first` and :func:`pandas.core.groupby.GroupBy.last` with ``as_index=False`` leading to the loss of timezone information (:issue:`15884`) - Bug in :meth:`DateFrame.resample` when downsampling across a DST boundary (:issue:`8531`) - Bug in date anchoring for :meth:`DateFrame.resample` with offset :class:`Day` when n > 1 (:issue:`24127`) diff --git a/pandas/_libs/window.pyx b/pandas/_libs/window.pyx index 5f2c0233a0f13..e8f3de64c3823 100644 --- a/pandas/_libs/window.pyx +++ b/pandas/_libs/window.pyx @@ -1339,7 +1339,10 @@ cdef _roll_min_max_variable(ndarray[numeric] values, Q.push_back(i) W.push_back(i) - output[N-1] = calc_mm(minp, nobs, values[Q.front()]) + if not Q.empty(): + output[N-1] = calc_mm(minp, nobs, values[Q.front()]) + else: + output[N-1] = NaN return output diff --git a/pandas/tests/test_window.py b/pandas/tests/test_window.py index 412f70a3cb516..e816d4c04344a 100644 --- a/pandas/tests/test_window.py +++ b/pandas/tests/test_window.py @@ -520,6 +520,26 @@ def test_closed(self): with pytest.raises(ValueError): df.rolling(window=3, closed='neither') + @pytest.mark.parametrize("func", ['min', 'max']) + def test_closed_one_entry(self, func): + # GH24718 + ser = pd.Series(data=[2], index=pd.date_range('2000', periods=1)) + result = getattr(ser.rolling('10D', closed='left'), func)() + tm.assert_series_equal(result, pd.Series([np.nan], index=ser.index)) + + @pytest.mark.parametrize("func", ['min', 'max']) + def test_closed_one_entry_groupby(self, func): + # GH24718 + ser = pd.DataFrame(data={'A': [1, 1, 2], 'B': [3, 2, 1]}, + index=pd.date_range('2000', periods=3)) + result = getattr( + ser.groupby('A', sort=False)['B'].rolling('10D', closed='left'), + func)() + exp_idx = pd.MultiIndex.from_arrays(arrays=[[1, 1, 2], ser.index], + names=('A', None)) + expected = pd.Series(data=[np.nan, 3, np.nan], index=exp_idx, name='B') + tm.assert_series_equal(result, expected) + @pytest.mark.parametrize("input_dtype", ['int', 'float']) @pytest.mark.parametrize("func,closed,expected", [ ('min', 'right', [0.0, 0, 0, 1, 2, 3, 4, 5, 6, 7]),