diff --git a/doc/source/whatsnew/v2.1.0.rst b/doc/source/whatsnew/v2.1.0.rst index 31293a42a3977..137f2e5c12211 100644 --- a/doc/source/whatsnew/v2.1.0.rst +++ b/doc/source/whatsnew/v2.1.0.rst @@ -618,7 +618,7 @@ Other - Bug in :func:`assert_almost_equal` now throwing assertion error for two unequal sets (:issue:`51727`) - Bug in :func:`assert_frame_equal` checks category dtypes even when asked not to check index type (:issue:`52126`) - Bug in :meth:`DataFrame.reindex` with a ``fill_value`` that should be inferred with a :class:`ExtensionDtype` incorrectly inferring ``object`` dtype (:issue:`52586`) -- Bug in :meth:`DataFrame.shift` and :meth:`Series.shift` when passing both "freq" and "fill_value" silently ignoring "fill_value" instead of raising ``ValueError`` (:issue:`53832`) +- Bug in :meth:`DataFrame.shift` and :meth:`Series.shift` and :meth:`DataFrameGroupBy.shift` when passing both "freq" and "fill_value" silently ignoring "fill_value" instead of raising ``ValueError`` (:issue:`53832`) - Bug in :meth:`DataFrame.shift` with ``axis=1`` on a :class:`DataFrame` with a single :class:`ExtensionDtype` column giving incorrect results (:issue:`53832`) - Bug in :meth:`Series.align`, :meth:`DataFrame.align`, :meth:`Series.reindex`, :meth:`DataFrame.reindex`, :meth:`Series.interpolate`, :meth:`DataFrame.interpolate`, incorrectly failing to raise with method="asfreq" (:issue:`53620`) - Bug in :meth:`Series.map` when giving a callable to an empty series, the returned series had ``object`` dtype. It now keeps the original dtype (:issue:`52384`) diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py index 5f9740b4dcefc..9d87a28093371 100644 --- a/pandas/core/groupby/groupby.py +++ b/pandas/core/groupby/groupby.py @@ -4911,7 +4911,7 @@ def shift( periods: int = 1, freq=None, axis: Axis | lib.NoDefault = lib.no_default, - fill_value=None, + fill_value=lib.no_default, ): """ Shift each group by periods observations. @@ -4934,6 +4934,9 @@ def shift( fill_value : optional The scalar value to use for newly introduced missing values. + .. versionchanged:: 2.1.0 + Will raise a ``ValueError`` if ``freq`` is provided too. + Returns ------- Series or DataFrame @@ -4991,6 +4994,8 @@ def shift( f = lambda x: x.shift(periods, freq, axis, fill_value) return self._python_apply_general(f, self._selected_obj, is_transform=True) + if fill_value is lib.no_default: + fill_value = None ids, _, ngroups = self.grouper.group_info res_indexer = np.zeros(len(ids), dtype=np.int64) diff --git a/pandas/tests/groupby/test_groupby_shift_diff.py b/pandas/tests/groupby/test_groupby_shift_diff.py index 656471b2f6eb0..cec8ea9d351cf 100644 --- a/pandas/tests/groupby/test_groupby_shift_diff.py +++ b/pandas/tests/groupby/test_groupby_shift_diff.py @@ -7,6 +7,7 @@ Series, Timedelta, Timestamp, + date_range, ) import pandas._testing as tm @@ -154,3 +155,21 @@ def test_multindex_empty_shift_with_fill(): shifted_with_fill = df.groupby(["a", "b"]).shift(1, fill_value=0) tm.assert_frame_equal(shifted, shifted_with_fill) tm.assert_index_equal(shifted.index, shifted_with_fill.index) + + +def test_shift_periods_freq(): + # GH 54093 + data = {"a": [1, 2, 3, 4, 5, 6], "b": [0, 0, 0, 1, 1, 1]} + df = DataFrame(data, index=date_range(start="20100101", periods=6)) + result = df.groupby(df.index).shift(periods=-2, freq="D") + expected = DataFrame(data, index=date_range(start="2009-12-30", periods=6)) + tm.assert_frame_equal(result, expected) + + +def test_shift_disallow_freq_and_fill_value(): + # GH 53832 + data = {"a": [1, 2, 3, 4, 5, 6], "b": [0, 0, 0, 1, 1, 1]} + df = DataFrame(data, index=date_range(start="20100101", periods=6)) + msg = "Cannot pass both 'freq' and 'fill_value' to (Series|DataFrame).shift" + with pytest.raises(ValueError, match=msg): + df.groupby(df.index).shift(periods=-2, freq="D", fill_value="1")