diff --git a/doc/source/whatsnew/v1.5.3.rst b/doc/source/whatsnew/v1.5.3.rst index 489a6fda9ffab..0b670219f830c 100644 --- a/doc/source/whatsnew/v1.5.3.rst +++ b/doc/source/whatsnew/v1.5.3.rst @@ -48,6 +48,7 @@ Other as pandas works toward compatibility with SQLAlchemy 2.0. - Reverted deprecation (:issue:`45324`) of behavior of :meth:`Series.__getitem__` and :meth:`Series.__setitem__` slicing with an integer :class:`Index`; this will remain positional (:issue:`49612`) +- A ``FutureWarning`` raised when attempting to set values inplace with :meth:`DataFrame.loc` or :meth:`DataFrame.loc` has been changed to a ``DeprecationWarning`` (:issue:`48673`) - .. --------------------------------------------------------------------------- diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index 198903f5fceff..dd06d9bee4428 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -2026,7 +2026,7 @@ def _setitem_single_column(self, loc: int, value, plane_indexer): "array. To retain the old behavior, use either " "`df[df.columns[i]] = newvals` or, if columns are non-unique, " "`df.isetitem(i, newvals)`", - FutureWarning, + DeprecationWarning, stacklevel=find_stack_level(), ) # TODO: how to get future behavior? diff --git a/pandas/tests/extension/base/setitem.py b/pandas/tests/extension/base/setitem.py index 8dbf7d47374a6..83b1679b0da7e 100644 --- a/pandas/tests/extension/base/setitem.py +++ b/pandas/tests/extension/base/setitem.py @@ -400,7 +400,7 @@ def test_setitem_frame_2d_values(self, data): warn = None if has_can_hold_element and not isinstance(data.dtype, PandasDtype): # PandasDtype excluded because it isn't *really* supported. - warn = FutureWarning + warn = DeprecationWarning with tm.assert_produces_warning(warn, match=msg): df.iloc[:] = df diff --git a/pandas/tests/frame/indexing/test_indexing.py b/pandas/tests/frame/indexing/test_indexing.py index acd742c54b908..e2a99348f45aa 100644 --- a/pandas/tests/frame/indexing/test_indexing.py +++ b/pandas/tests/frame/indexing/test_indexing.py @@ -785,7 +785,7 @@ def test_getitem_setitem_float_labels(self, using_array_manager): assert len(result) == 5 cp = df.copy() - warn = FutureWarning if using_array_manager else None + warn = DeprecationWarning if using_array_manager else None msg = "will attempt to set the values inplace" with tm.assert_produces_warning(warn, match=msg): cp.loc[1.0:5.0] = 0 diff --git a/pandas/tests/frame/indexing/test_setitem.py b/pandas/tests/frame/indexing/test_setitem.py index cf0ff4e3603f3..e33c6d6a805cf 100644 --- a/pandas/tests/frame/indexing/test_setitem.py +++ b/pandas/tests/frame/indexing/test_setitem.py @@ -408,7 +408,7 @@ def test_setitem_frame_length_0_str_key(self, indexer): def test_setitem_frame_duplicate_columns(self, using_array_manager): # GH#15695 - warn = FutureWarning if using_array_manager else None + warn = DeprecationWarning if using_array_manager else None msg = "will attempt to set the values inplace" cols = ["A", "B", "C"] * 2 diff --git a/pandas/tests/frame/indexing/test_where.py b/pandas/tests/frame/indexing/test_where.py index fba8978d2128c..c7e0a10c0d7d0 100644 --- a/pandas/tests/frame/indexing/test_where.py +++ b/pandas/tests/frame/indexing/test_where.py @@ -384,7 +384,7 @@ def test_where_datetime(self, using_array_manager): expected = df.copy() expected.loc[[0, 1], "A"] = np.nan - warn = FutureWarning if using_array_manager else None + warn = DeprecationWarning if using_array_manager else None msg = "will attempt to set the values inplace" with tm.assert_produces_warning(warn, match=msg): expected.loc[:, "C"] = np.nan @@ -571,7 +571,7 @@ def test_where_axis_multiple_dtypes(self, using_array_manager): d2 = df.copy().drop(1, axis=1) expected = df.copy() - warn = FutureWarning if using_array_manager else None + warn = DeprecationWarning if using_array_manager else None msg = "will attempt to set the values inplace" with tm.assert_produces_warning(warn, match=msg): expected.loc[:, 1] = np.nan diff --git a/pandas/tests/frame/methods/test_dropna.py b/pandas/tests/frame/methods/test_dropna.py index 62351aa89c914..53d9f75494d92 100644 --- a/pandas/tests/frame/methods/test_dropna.py +++ b/pandas/tests/frame/methods/test_dropna.py @@ -221,7 +221,7 @@ def test_dropna_with_duplicate_columns(self): df.iloc[0, 0] = np.nan df.iloc[1, 1] = np.nan msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.iloc[:, 3] = np.nan expected = df.dropna(subset=["A", "B", "C"], how="all") expected.columns = ["A", "A", "B", "C"] diff --git a/pandas/tests/frame/methods/test_rename.py b/pandas/tests/frame/methods/test_rename.py index f4443953a0d52..405518c372b2c 100644 --- a/pandas/tests/frame/methods/test_rename.py +++ b/pandas/tests/frame/methods/test_rename.py @@ -178,7 +178,9 @@ def test_rename_nocopy(self, float_frame, using_copy_on_write): # TODO(CoW) this also shouldn't warn in case of CoW, but the heuristic # checking if the array shares memory doesn't work if CoW happened - with tm.assert_produces_warning(FutureWarning if using_copy_on_write else None): + with tm.assert_produces_warning( + DeprecationWarning if using_copy_on_write else None + ): # This loc setitem already happens inplace, so no warning # that this will change in the future renamed.loc[:, "foo"] = 1.0 diff --git a/pandas/tests/frame/methods/test_shift.py b/pandas/tests/frame/methods/test_shift.py index bfc3c8e0a25eb..9b4dcf58590e3 100644 --- a/pandas/tests/frame/methods/test_shift.py +++ b/pandas/tests/frame/methods/test_shift.py @@ -372,7 +372,7 @@ def test_shift_duplicate_columns(self, using_array_manager): warn = None if using_array_manager: - warn = FutureWarning + warn = DeprecationWarning shifted = [] for columns in column_lists: diff --git a/pandas/tests/frame/test_constructors.py b/pandas/tests/frame/test_constructors.py index b4f027f3a832a..16021facb3986 100644 --- a/pandas/tests/frame/test_constructors.py +++ b/pandas/tests/frame/test_constructors.py @@ -2604,7 +2604,9 @@ def check_views(c_only: bool = False): # FIXME(GH#35417): until GH#35417, iloc.setitem into EA values does not preserve # view, so we have to check in the other direction - with tm.assert_produces_warning(FutureWarning, match="will attempt to set"): + with tm.assert_produces_warning( + DeprecationWarning, match="will attempt to set" + ): df.iloc[:, 2] = pd.array([45, 46], dtype=c.dtype) assert df.dtypes.iloc[2] == c.dtype if not copy and not using_copy_on_write: diff --git a/pandas/tests/frame/test_nonunique_indexes.py b/pandas/tests/frame/test_nonunique_indexes.py index 2c28800fb181f..38861a2b04409 100644 --- a/pandas/tests/frame/test_nonunique_indexes.py +++ b/pandas/tests/frame/test_nonunique_indexes.py @@ -323,7 +323,9 @@ def test_dup_columns_across_dtype(self): def test_set_value_by_index(self, using_array_manager): # See gh-12344 warn = ( - FutureWarning if using_array_manager and not is_platform_windows() else None + DeprecationWarning + if using_array_manager and not is_platform_windows() + else None ) msg = "will attempt to set the values inplace" diff --git a/pandas/tests/frame/test_stack_unstack.py b/pandas/tests/frame/test_stack_unstack.py index 69e5d5e3d5447..e22559802cbec 100644 --- a/pandas/tests/frame/test_stack_unstack.py +++ b/pandas/tests/frame/test_stack_unstack.py @@ -23,7 +23,7 @@ class TestDataFrameReshape: def test_stack_unstack(self, float_frame, using_array_manager): - warn = FutureWarning if using_array_manager else None + warn = DeprecationWarning if using_array_manager else None msg = "will attempt to set the values inplace" df = float_frame.copy() diff --git a/pandas/tests/indexing/multiindex/test_loc.py b/pandas/tests/indexing/multiindex/test_loc.py index d4354766a203b..5cf044280b391 100644 --- a/pandas/tests/indexing/multiindex/test_loc.py +++ b/pandas/tests/indexing/multiindex/test_loc.py @@ -541,9 +541,9 @@ def test_loc_setitem_single_column_slice(): ) expected = df.copy() msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[:, "B"] = np.arange(4) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): expected.iloc[:, 2] = np.arange(4) tm.assert_frame_equal(df, expected) diff --git a/pandas/tests/indexing/test_iloc.py b/pandas/tests/indexing/test_iloc.py index 8cc6b6e73aaea..dcc95d9e41a5a 100644 --- a/pandas/tests/indexing/test_iloc.py +++ b/pandas/tests/indexing/test_iloc.py @@ -84,7 +84,7 @@ def test_iloc_setitem_fullcol_categorical(self, indexer, key, using_array_manage overwrite = isinstance(key, slice) and key == slice(None) warn = None if overwrite: - warn = FutureWarning + warn = DeprecationWarning msg = "will attempt to set the values inplace instead" with tm.assert_produces_warning(warn, match=msg): indexer(df)[key, 0] = cat @@ -108,7 +108,7 @@ def test_iloc_setitem_fullcol_categorical(self, indexer, key, using_array_manage frame = DataFrame({0: np.array([0, 1, 2], dtype=object), 1: range(3)}) df = frame.copy() orig_vals = df.values - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): indexer(df)[key, 0] = cat expected = DataFrame({0: cat, 1: range(3)}) tm.assert_frame_equal(df, expected) @@ -904,7 +904,7 @@ def test_iloc_setitem_categorical_updates_inplace(self, using_copy_on_write): # This should modify our original values in-place msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.iloc[:, 0] = cat[::-1] if not using_copy_on_write: @@ -1314,7 +1314,7 @@ def test_iloc_setitem_dtypes_duplicate_columns( # GH#22035 df = DataFrame([[init_value, "str", "str2"]], columns=["a", "b", "b"]) msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.iloc[:, 0] = df.iloc[:, 0].astype(dtypes) expected_df = DataFrame( diff --git a/pandas/tests/indexing/test_indexing.py b/pandas/tests/indexing/test_indexing.py index 069e5a62895af..210c75b075011 100644 --- a/pandas/tests/indexing/test_indexing.py +++ b/pandas/tests/indexing/test_indexing.py @@ -550,7 +550,7 @@ def test_astype_assignment(self): df = df_orig.copy() msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.iloc[:, 0:2] = df.iloc[:, 0:2].astype(np.int64) expected = DataFrame( [[1, 2, "3", ".4", 5, 6.0, "foo"]], columns=list("ABCDEFG") @@ -558,7 +558,7 @@ def test_astype_assignment(self): tm.assert_frame_equal(df, expected) df = df_orig.copy() - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.iloc[:, 0:2] = df.iloc[:, 0:2]._convert(datetime=True, numeric=True) expected = DataFrame( [[1, 2, "3", ".4", 5, 6.0, "foo"]], columns=list("ABCDEFG") @@ -567,7 +567,7 @@ def test_astype_assignment(self): # GH5702 (loc) df = df_orig.copy() - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[:, "A"] = df.loc[:, "A"].astype(np.int64) expected = DataFrame( [[1, "2", "3", ".4", 5, 6.0, "foo"]], columns=list("ABCDEFG") @@ -575,7 +575,7 @@ def test_astype_assignment(self): tm.assert_frame_equal(df, expected) df = df_orig.copy() - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[:, ["B", "C"]] = df.loc[:, ["B", "C"]].astype(np.int64) expected = DataFrame( [["1", 2, 3, ".4", 5, 6.0, "foo"]], columns=list("ABCDEFG") @@ -586,13 +586,13 @@ def test_astype_assignment_full_replacements(self): # full replacements / no nans df = DataFrame({"A": [1.0, 2.0, 3.0, 4.0]}) msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.iloc[:, 0] = df["A"].astype(np.int64) expected = DataFrame({"A": [1, 2, 3, 4]}) tm.assert_frame_equal(df, expected) df = DataFrame({"A": [1.0, 2.0, 3.0, 4.0]}) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[:, "A"] = df["A"].astype(np.int64) expected = DataFrame({"A": [1, 2, 3, 4]}) tm.assert_frame_equal(df, expected) diff --git a/pandas/tests/indexing/test_loc.py b/pandas/tests/indexing/test_loc.py index e62fb98b0782d..235ad3d213a62 100644 --- a/pandas/tests/indexing/test_loc.py +++ b/pandas/tests/indexing/test_loc.py @@ -368,7 +368,7 @@ def test_loc_setitem_dtype(self): df = DataFrame({"id": ["A"], "a": [1.2], "b": [0.0], "c": [-2.5]}) cols = ["a", "b", "c"] msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[:, cols] = df.loc[:, cols].astype("float32") expected = DataFrame( @@ -633,11 +633,11 @@ def test_loc_setitem_consistency_slice_column_len(self): df = DataFrame(values, index=mi, columns=cols) msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[:, ("Respondent", "StartDate")] = to_datetime( df.loc[:, ("Respondent", "StartDate")] ) - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[:, ("Respondent", "EndDate")] = to_datetime( df.loc[:, ("Respondent", "EndDate")] ) @@ -720,7 +720,7 @@ def test_loc_setitem_frame_with_reindex_mixed(self): df = DataFrame(index=[3, 5, 4], columns=["A", "B"], dtype=float) df["B"] = "string" msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[[4, 3, 5], "A"] = np.array([1, 2, 3], dtype="int64") ser = Series([2, 3, 1], index=[3, 5, 4], dtype="int64") expected = DataFrame({"A": ser}) @@ -732,7 +732,7 @@ def test_loc_setitem_frame_with_inverted_slice(self): df = DataFrame(index=[1, 2, 3], columns=["A", "B"], dtype=float) df["B"] = "string" msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[slice(3, 0, -1), "A"] = np.array([1, 2, 3], dtype="int64") expected = DataFrame({"A": [3, 2, 1], "B": "string"}, index=[1, 2, 3]) tm.assert_frame_equal(df, expected) @@ -909,7 +909,7 @@ def test_loc_setitem_missing_columns(self, index, box, expected): warn = None if isinstance(index[0], slice) and index[0] == slice(None): - warn = FutureWarning + warn = DeprecationWarning msg = "will attempt to set the values inplace instead" with tm.assert_produces_warning(warn, match=msg): @@ -1425,7 +1425,7 @@ def test_loc_setitem_single_row_categorical(self): categories = Categorical(df["Alpha"], categories=["a", "b", "c"]) msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[:, "Alpha"] = categories result = df["Alpha"] @@ -3211,3 +3211,11 @@ def test_getitem_loc_str_periodindex(self): index = pd.period_range(start="2000", periods=20, freq="B") series = Series(range(20), index=index) assert series.loc["2000-01-14"] == 9 + + def test_deprecation_warnings_raised_loc(self): + # GH#48673 + with tm.assert_produces_warning(DeprecationWarning): + values = np.arange(4).reshape(2, 2) + df = DataFrame(values, columns=["a", "b"]) + new = np.array([10, 11]).astype(np.int16) + df.loc[:, "a"] = new diff --git a/pandas/tests/indexing/test_partial.py b/pandas/tests/indexing/test_partial.py index 938056902e745..f973bdf7ea6f6 100644 --- a/pandas/tests/indexing/test_partial.py +++ b/pandas/tests/indexing/test_partial.py @@ -312,7 +312,7 @@ def test_partial_setting_frame(self, using_array_manager): df = df_orig.copy() df["B"] = df["B"].astype(np.float64) msg = "will attempt to set the values inplace instead" - with tm.assert_produces_warning(FutureWarning, match=msg): + with tm.assert_produces_warning(DeprecationWarning, match=msg): df.loc[:, "B"] = df.loc[:, "A"] tm.assert_frame_equal(df, expected)