Skip to content

Commit

Permalink
DEPR: non-keyword arguments in any (pandas-dev#44896)
Browse files Browse the repository at this point in the history
* tighten return type in any

* correct overload definitions

* add overload def for NDFrame input

* remove overload defs and define function any in sub-classes

* add overload defs for level

* correct default val in overload defs

* deprecate non-keyword args

* add whatsnew note

* modify return types and add tests

* move non-keyword deprecation to generic

* correct deprecation decorators

* remove imports in test assertions

* place deprecate_nonkeyword at correct place

* remove changes from frame.py, series.py

* readd changes in frame, series without actual implementations

* place deprecate_nonkeyword at other place

* add name argument to deprecate_non_keyword_args decorator

* add test for name in deprecate_nonkeyword_args

* remove changes from frame.py, series.py

* correct stacklevel in warning

* correct stacklevel

* set stacklevel to default

* move deprecation message to whatsnew v1.5.0.rst

* add name parameter in deprecate_non_keyword_args docstring

* correct whitespace in deprecate_nonkeyword_args docstring

* update any non-keyword args in other tests

* update any in doc

* update remaining any() calls in pandas/core

* correct docstring of isocalendar in pandas/core/indexes/accessors.py

Co-authored-by: Marco Edward Gorelli <marcogorelli@protonmail.com>
  • Loading branch information
2 people authored and yehoshuadimarsky committed Jul 13, 2022
1 parent 285127c commit 94d52a1
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 9 deletions.
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.13.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ Enhancements
other = pd.DataFrame({'A': [1, 3, 3, 7], 'B': ['e', 'f', 'f', 'e']})
mask = dfi.isin(other)
mask
dfi[mask.any(1)]
dfi[mask.any(axis=1)]
- ``Series`` now supports a ``to_frame`` method to convert it to a single-column DataFrame (:issue:`5164`)

Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.5.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ Other Deprecations
- Deprecated behavior of method :meth:`DataFrame.quantile`, attribute ``numeric_only`` will default False. Including datetime/timedelta columns in the result (:issue:`7308`).
- Deprecated :attr:`Timedelta.freq` and :attr:`Timedelta.is_populated` (:issue:`46430`)
- Deprecated :attr:`Timedelta.delta` (:issue:`46476`)
- Deprecated passing arguments as positional in :meth:`DataFrame.any` and :meth:`Series.any` (:issue:`44802`)
- Deprecated the ``closed`` argument in :meth:`interval_range` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`)
- Deprecated the methods :meth:`DataFrame.mad`, :meth:`Series.mad`, and the corresponding groupby methods (:issue:`11787`)

Expand Down
10 changes: 8 additions & 2 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -7224,7 +7224,7 @@ def asof(self, where, subset=None):
if not isinstance(where, Index):
where = Index(where) if is_list else Index([where])

nulls = self.isna() if is_series else self[subset].isna().any(1)
nulls = self.isna() if is_series else self[subset].isna().any(axis=1)
if nulls.all():
if is_series:
self = cast("Series", self)
Expand Down Expand Up @@ -10517,7 +10517,7 @@ def any(
skipna: bool_t = True,
level: Level | None = None,
**kwargs,
) -> Series | bool_t:
) -> DataFrame | Series | bool_t:
return self._logical_func(
"any", nanops.nanany, axis, bool_only, skipna, level, **kwargs
)
Expand Down Expand Up @@ -10941,6 +10941,12 @@ def _add_numeric_operations(cls):
"""
axis_descr, name1, name2 = _doc_params(cls)

@deprecate_nonkeyword_arguments(
version=None,
allowed_args=["self"],
stacklevel=find_stack_level() - 1,
name="DataFrame.any and Series.any",
)
@doc(
_bool_doc,
desc=_any_desc,
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/missing.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def find_valid_index(values, *, how: str) -> int | None:
is_valid = ~isna(values)

if values.ndim == 2:
is_valid = is_valid.any(1) # reduce axis 1
is_valid = is_valid.any(axis=1) # reduce axis 1

if how == "first":
idxpos = is_valid[::].argmax()
Expand Down
6 changes: 3 additions & 3 deletions pandas/tests/frame/test_reductions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1066,11 +1066,11 @@ def test_any_all_extra(self):
},
index=["a", "b", "c"],
)
result = df[["A", "B"]].any(1)
result = df[["A", "B"]].any(axis=1)
expected = Series([True, True, False], index=["a", "b", "c"])
tm.assert_series_equal(result, expected)

result = df[["A", "B"]].any(1, bool_only=True)
result = df[["A", "B"]].any(axis=1, bool_only=True)
tm.assert_series_equal(result, expected)

result = df.all(1)
Expand Down Expand Up @@ -1119,7 +1119,7 @@ def test_any_datetime(self):
]
df = DataFrame({"A": float_data, "B": datetime_data})

result = df.any(1)
result = df.any(axis=1)
expected = Series([True, True, True, False])
tm.assert_series_equal(result, expected)

Expand Down
22 changes: 22 additions & 0 deletions pandas/tests/groupby/test_any_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,28 @@ def test_any():
tm.assert_frame_equal(result, expected)


def test_any_non_keyword_deprecation():
df = DataFrame({"A": [1, 2], "B": [0, 2], "C": [0, 0]})
msg = (
"In a future version of pandas all arguments of "
"DataFrame.any and Series.any will be keyword-only."
)
with tm.assert_produces_warning(FutureWarning, match=msg):
result = df.any("index", None)
expected = Series({"A": True, "B": True, "C": False})
tm.assert_series_equal(result, expected)

s = Series([False, False, False])
msg = (
"In a future version of pandas all arguments of "
"DataFrame.any and Series.any will be keyword-only."
)
with tm.assert_produces_warning(FutureWarning, match=msg):
result = s.any("index")
expected = False
tm.assert_equal(result, expected)


@pytest.mark.parametrize("bool_agg_func", ["any", "all"])
def test_bool_aggs_dup_column_labels(bool_agg_func):
# 21668
Expand Down
17 changes: 16 additions & 1 deletion pandas/tests/util/test_deprecate_nonkeyword_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import pandas._testing as tm


@deprecate_nonkeyword_arguments(version="1.1", allowed_args=["a", "b"])
@deprecate_nonkeyword_arguments(
version="1.1", allowed_args=["a", "b"], name="f_add_inputs"
)
def f(a, b=0, c=0, d=0):
return a + b + c + d

Expand Down Expand Up @@ -44,6 +46,19 @@ def test_four_arguments():
assert f(1, 2, 3, 4) == 10


def test_three_arguments_with_name_in_warning():
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
assert f(6, 3, 3) == 12
assert len(w) == 1
for actual_warning in w:
assert actual_warning.category == FutureWarning
assert str(actual_warning.message) == (
"Starting with pandas version 1.1 all arguments of f_add_inputs "
"except for the arguments 'a' and 'b' will be keyword-only."
)


@deprecate_nonkeyword_arguments(version="1.1")
def g(a, b=0, c=0, d=0):
with tm.assert_produces_warning(None):
Expand Down
8 changes: 7 additions & 1 deletion pandas/util/_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ def deprecate_nonkeyword_arguments(
version: str | None,
allowed_args: list[str] | None = None,
stacklevel: int = 2,
name: str | None = None,
) -> Callable[[F], F]:
"""
Decorator to deprecate a use of non-keyword arguments of a function.
Expand All @@ -281,6 +282,11 @@ def deprecate_nonkeyword_arguments(
stacklevel : int, default=2
The stack level for warnings.warn
name : str, optional
The specific name of the function to show in the warning
message. If None, then the Qualified name of the function
is used.
"""

def decorate(func):
Expand All @@ -296,7 +302,7 @@ def decorate(func):
num_allow_args = len(allow_args)
msg = (
f"{future_version_msg(version)} all arguments of "
f"{func.__qualname__}{{arguments}} will be keyword-only."
f"{name or func.__qualname__}{{arguments}} will be keyword-only."
)

@wraps(func)
Expand Down

0 comments on commit 94d52a1

Please sign in to comment.