diff --git a/doc/source/whatsnew/v2.3.0.rst b/doc/source/whatsnew/v2.3.0.rst index 1f1b0c7d7195a..b6de33002251b 100644 --- a/doc/source/whatsnew/v2.3.0.rst +++ b/doc/source/whatsnew/v2.3.0.rst @@ -108,6 +108,7 @@ Performance improvements Bug fixes ~~~~~~~~~ +Fixed bug in :meth:`Series.diff` and :meth:`algorithms.diff` for no arg validation unlike :meth:`Dataframe.diff` for periods. (: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/io/xml/test_xml.py b/pandas/tests/io/xml/test_xml.py index 5451f7b2f16f5..2e1197cff8875 100644 --- a/pandas/tests/io/xml/test_xml.py +++ b/pandas/tests/io/xml/test_xml.py @@ -497,10 +497,9 @@ def test_wrong_file_path(parser): ) filename = os.path.join("data", "html", "books.xml") - with pytest.raises( - FutureWarning, - match=msg, - ): + with tm.assert_produces_warning( + FutureWarning, + match=msg): read_xml(filename, parser=parser) @@ -1369,7 +1368,8 @@ def test_empty_stylesheet(val): ) kml = os.path.join("data", "xml", "cta_rail_lines.kml") - with pytest.raises(FutureWarning, match=msg): + # 56716: Use assert_produces_warning instead of pytest.raises to show FutureWarning + with tm.assert_produces_warning(FutureWarning, match=msg): read_xml(kml, stylesheet=val) 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()