diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index 258e391b9220c..ce20006a8d3db 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -681,6 +681,7 @@ Deprecations - Deprecated passing arguments as positional (except for ``"method"``) in :meth:`DataFrame.interpolate` and :meth:`Series.interpolate` (:issue:`41485`) - Deprecated passing arguments (apart from ``value``) as positional in :meth:`DataFrame.fillna` and :meth:`Series.fillna` (:issue:`41485`) - Deprecated construction of :class:`Series` or :class:`DataFrame` with ``DatetimeTZDtype`` data and ``datetime64[ns]`` dtype. Use ``Series(data).dt.tz_localize(None)`` instead (:issue:`41555`,:issue:`33401`) +- Deprecated passing arguments as positional in :meth:`DataFrame.where` and :meth:`Series.where` (other than ``"cond"`` and ``"other"``) (:issue:`41485`) .. _whatsnew_130.deprecations.nuisance_columns: diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 7b564d55a342c..a24585b68a9ea 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -10688,6 +10688,21 @@ def interpolate( **kwargs, ) + @deprecate_nonkeyword_arguments( + version=None, allowed_args=["self", "cond", "other"] + ) + def where( + self, + cond, + other=np.nan, + inplace=False, + axis=None, + level=None, + errors="raise", + try_cast=lib.no_default, + ): + return super().where(cond, other, inplace, axis, level, errors, try_cast) + DataFrame._add_numeric_operations() diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 6d7c803685255..ffebb30cda8db 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -9073,7 +9073,6 @@ def _where( result = self._constructor(new_data) return result.__finalize__(self) - @final @doc( klass=_shared_doc_kwargs["klass"], cond="True", @@ -9221,7 +9220,7 @@ def where( "try_cast keyword is deprecated and will be removed in a " "future version", FutureWarning, - stacklevel=2, + stacklevel=4, ) return self._where(cond, other, inplace, axis, level, errors=errors) diff --git a/pandas/core/series.py b/pandas/core/series.py index 4eba0db7e98ec..2da98e5dfd020 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -5310,6 +5310,21 @@ def interpolate( **kwargs, ) + @deprecate_nonkeyword_arguments( + version=None, allowed_args=["self", "cond", "other"] + ) + def where( + self, + cond, + other=np.nan, + inplace=False, + axis=None, + level=None, + errors="raise", + try_cast=lib.no_default, + ): + return super().where(cond, other, inplace, axis, level, errors, try_cast) + # ---------------------------------------------------------------------- # Add index _AXIS_ORDERS = ["index"] diff --git a/pandas/tests/frame/indexing/test_where.py b/pandas/tests/frame/indexing/test_where.py index 32a499f6e9168..0405d150c0c04 100644 --- a/pandas/tests/frame/indexing/test_where.py +++ b/pandas/tests/frame/indexing/test_where.py @@ -757,3 +757,17 @@ def test_where_none_nan_coerce(): ) result = expected.where(expected.notnull(), None) tm.assert_frame_equal(result, expected) + + +def test_where_non_keyword_deprecation(): + # GH 41485 + s = DataFrame(range(5)) + msg = ( + "In a future version of pandas all arguments of " + "DataFrame.where except for the arguments 'cond' " + "and 'other' will be keyword-only" + ) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = s.where(s > 1, 10, False) + expected = DataFrame([10, 10, 2, 3, 4]) + tm.assert_frame_equal(expected, result) diff --git a/pandas/tests/series/indexing/test_where.py b/pandas/tests/series/indexing/test_where.py index b13fd18405839..0c6b9bd924759 100644 --- a/pandas/tests/series/indexing/test_where.py +++ b/pandas/tests/series/indexing/test_where.py @@ -141,6 +141,20 @@ def test_where(): tm.assert_series_equal(rs, expected) +def test_where_non_keyword_deprecation(): + # GH 41485 + s = Series(range(5)) + msg = ( + "In a future version of pandas all arguments of " + "Series.where except for the arguments 'cond' " + "and 'other' will be keyword-only" + ) + with tm.assert_produces_warning(FutureWarning, match=msg): + result = s.where(s > 1, 10, False) + expected = Series([10, 10, 2, 3, 4]) + tm.assert_series_equal(expected, result) + + def test_where_error(): s = Series(np.random.randn(5)) cond = s > 0