diff --git a/doc/source/whatsnew/v2.3.0.rst b/doc/source/whatsnew/v2.3.0.rst index 1f1b0c7d7195a..c0692dba32a72 100644 --- a/doc/source/whatsnew/v2.3.0.rst +++ b/doc/source/whatsnew/v2.3.0.rst @@ -108,6 +108,8 @@ Performance improvements Bug fixes ~~~~~~~~~ +- Fixed bug in :meth:`Series.diff` allowing non-integer values for the ``periods`` argument. (:issue:`56607`) + Categorical ^^^^^^^^^^^ diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 76fdcefd03407..128477dac562e 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -47,6 +47,7 @@ is_complex_dtype, is_dict_like, is_extension_array_dtype, + is_float, is_float_dtype, is_integer, is_integer_dtype, @@ -1361,7 +1362,12 @@ def diff(arr, n: int, axis: AxisInt = 0): shifted """ - n = int(n) + # added a check on the integer value of period + # see https://github.com/pandas-dev/pandas/issues/56607 + if not lib.is_integer(n): + if not (is_float(n) and n.is_integer()): + raise ValueError("periods must be an integer") + n = int(n) na = np.nan dtype = arr.dtype diff --git a/pandas/core/series.py b/pandas/core/series.py index 1f9ac8511476e..90073e21cfd66 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -72,6 +72,7 @@ ) from pandas.core.dtypes.common import ( is_dict_like, + is_float, is_integer, is_iterator, is_list_like, @@ -3102,6 +3103,9 @@ def diff(self, periods: int = 1) -> Series: -------- {examples} """ + if not lib.is_integer(periods): + if not (is_float(periods) and periods.is_integer()): + raise ValueError("periods must be an integer") result = algorithms.diff(self._values, periods) return self._constructor(result, index=self.index, copy=False).__finalize__( self, method="diff" diff --git a/pandas/tests/series/methods/test_diff.py b/pandas/tests/series/methods/test_diff.py index 18de81a927c3a..a46389087f87b 100644 --- a/pandas/tests/series/methods/test_diff.py +++ b/pandas/tests/series/methods/test_diff.py @@ -10,6 +10,11 @@ class TestSeriesDiff: + def test_diff_series_requires_integer(self): + series = Series(np.random.default_rng(2).standard_normal(2)) + with pytest.raises(ValueError, match="periods must be an integer"): + series.diff(1.5) + def test_diff_np(self): # TODO(__array_function__): could make np.diff return a Series # matching ser.diff()