From 69eb1ae6e45840625d0517743254cd2ead0edcf6 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 22 Nov 2022 11:09:05 -0800 Subject: [PATCH 1/3] DEPR/API: DataFrame.shift(axis=1, fill_value=inty) --- doc/source/whatsnew/v2.0.0.rst | 1 + pandas/core/frame.py | 7 ------- pandas/tests/frame/methods/test_shift.py | 10 ++++------ 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 20e99d007c798..96f921de3793e 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -348,6 +348,7 @@ Other API changes - Changed behavior of :class:`Index` constructor with sequence containing at least one ``NaT`` and everything else either ``None`` or ``NaN`` to infer ``datetime64[ns]`` dtype instead of ``object``, matching :class:`Series` behavior (:issue:`49340`) - :func:`read_stata` with parameter ``index_col`` set to ``None`` (the default) will now set the index on the returned :class:`DataFrame` to a :class:`RangeIndex` instead of a :class:`Int64Index` (:issue:`49745`) - Changed behavior of :class:`Index` constructor with an object-dtype ``numpy.ndarray`` containing all-``bool`` values or all-complex values, this will now retain object dtype, consistent with the :class:`Series` behavior (:issue:`49594`) +- Changed behavior of :meth:`DataFrame.shift` with ``axis=1``, an integer ``fill_value``, and homogeneous datetime-like dtype, this now fills new columns with integer dtypes instead of casting to datetimelike (:issue:`??`) - .. --------------------------------------------------------------------------- diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 7b181a3e8e391..e553c941d1b89 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -5641,14 +5641,7 @@ def shift( # keep the same dtype (i.e. the _can_hold_element check) # then we can go through the reindex_indexer path # (and avoid casting logic in the Block method). - # The exception to this (until 2.0) is datetimelike - # dtypes with integers, which cast. not can_hold_element(arrays[0], fill_value) - # TODO(2.0): remove special case for integer-with-datetimelike - # once deprecation is enforced - and not ( - lib.is_integer(fill_value) and needs_i8_conversion(arrays[0].dtype) - ) ): # GH#35488 we need to watch out for multi-block cases # We only get here with fill_value not-lib.no_default diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index c44c0bd566585..fe9ad0d0e6639 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -516,17 +516,15 @@ def test_shift_dt64values_int_fill_deprecated(self): df2 = DataFrame({"A": ser, "B": ser}) df2._consolidate_inplace() - with pytest.raises(TypeError, match="value should be a"): - df2.shift(1, axis=1, fill_value=0) + result = df2.shift(1, axis=1, fill_value=0) + expected = DataFrame({"A": [0, 0], "B": df2["A"]}) + tm.assert_frame_equal(result, expected) - # same thing but not consolidated - # This isn't great that we get different behavior, but - # that will go away when the deprecation is enforced + # same thing but not consolidated; pre-2.0 we got different behavior df3 = DataFrame({"A": ser}) df3["B"] = ser assert len(df3._mgr.arrays) == 2 result = df3.shift(1, axis=1, fill_value=0) - expected = DataFrame({"A": [0, 0], "B": df2["A"]}) tm.assert_frame_equal(result, expected) @pytest.mark.parametrize( From b7fc64ef7260a8ee4a00a56576d175b7b404e7a4 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 22 Nov 2022 11:10:01 -0800 Subject: [PATCH 2/3] GH ref --- doc/source/whatsnew/v2.0.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index 96f921de3793e..48824f209982b 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -348,7 +348,7 @@ Other API changes - Changed behavior of :class:`Index` constructor with sequence containing at least one ``NaT`` and everything else either ``None`` or ``NaN`` to infer ``datetime64[ns]`` dtype instead of ``object``, matching :class:`Series` behavior (:issue:`49340`) - :func:`read_stata` with parameter ``index_col`` set to ``None`` (the default) will now set the index on the returned :class:`DataFrame` to a :class:`RangeIndex` instead of a :class:`Int64Index` (:issue:`49745`) - Changed behavior of :class:`Index` constructor with an object-dtype ``numpy.ndarray`` containing all-``bool`` values or all-complex values, this will now retain object dtype, consistent with the :class:`Series` behavior (:issue:`49594`) -- Changed behavior of :meth:`DataFrame.shift` with ``axis=1``, an integer ``fill_value``, and homogeneous datetime-like dtype, this now fills new columns with integer dtypes instead of casting to datetimelike (:issue:`??`) +- Changed behavior of :meth:`DataFrame.shift` with ``axis=1``, an integer ``fill_value``, and homogeneous datetime-like dtype, this now fills new columns with integer dtypes instead of casting to datetimelike (:issue:`49842`) - .. --------------------------------------------------------------------------- From d44d2da4bdc1818c8b6e2c40aeadabcb67b8ae7f Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 22 Nov 2022 12:15:35 -0800 Subject: [PATCH 3/3] un-xfail on ArrayManager --- pandas/tests/frame/methods/test_shift.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index fe9ad0d0e6639..4a207eac9fa80 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -500,7 +500,6 @@ def test_datetime_frame_shift_with_freq_error( with pytest.raises(ValueError, match=msg): no_freq.shift(freq="infer") - @td.skip_array_manager_not_yet_implemented # TODO(ArrayManager) axis=1 support def test_shift_dt64values_int_fill_deprecated(self): # GH#31971 ser = Series([pd.Timestamp("2020-01-01"), pd.Timestamp("2020-01-02")])