Skip to content

API: Rename arg to func in Series.map #61264

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Apr 14, 2025
1 change: 1 addition & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ Other API changes
- Index set operations (like union or intersection) will now ignore the dtype of
an empty ``RangeIndex`` or empty ``Index`` with object dtype when determining
the dtype of the resulting Index (:issue:`60797`)
- Renamed the ``arg`` parameter of ``Series.map`` to ``func``. (:issue:`61260`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be in deprecations?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it there. Since it's renaming a parameter both deprecations and API changed made sense, but I have no preference.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - the way I read API changes is "things I need to change to not have my code break when upgrading". As this is a deprecation, users don't need to do that just yet.


.. ---------------------------------------------------------------------------
.. _whatsnew_300.deprecations:
Expand Down
28 changes: 22 additions & 6 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
doc,
set_module,
)
from pandas.util._exceptions import (
find_stack_level,
)
from pandas.util._validators import (
validate_ascending,
validate_bool_kwarg,
Expand Down Expand Up @@ -4320,7 +4323,7 @@ def unstack(

def map(
self,
arg: Callable | Mapping | Series,
func: Callable | Mapping | Series | None = None,
na_action: Literal["ignore"] | None = None,
**kwargs,
) -> Series:
Expand All @@ -4333,8 +4336,8 @@ def map(

Parameters
----------
arg : function, collections.abc.Mapping subclass or Series
Mapping correspondence.
func : function, collections.abc.Mapping subclass or Series
Function or mapping correspondence.
na_action : {None, 'ignore'}, default None
If 'ignore', propagate NaN values, without passing them to the
mapping correspondence.
Expand Down Expand Up @@ -4404,9 +4407,22 @@ def map(
3 I am a rabbit
dtype: object
"""
if callable(arg):
arg = functools.partial(arg, **kwargs)
new_values = self._map_values(arg, na_action=na_action)
if func is None:
if "arg" in kwargs:
Comment on lines +4410 to +4411
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noting this won't be backwards compatible with the use Series.map(arg=foo, func=myfunc) where myfunc is an argument of foo. This seems unlikely enough that I am okay here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are totally right. In my first implementation I was raising an exception, and then thought it would be better to allow using arg as an argument name of the udf. If we want to be very conservative we could raise now, and stop raising when we remove the deprecation and arg is no longer accepted as the argument name of the function.

But as you, I think is better to just let that unlikely case break compatibility.

# `.map(arg=my_func)`
func = kwargs.pop("arg")
warnings.warn(
"The parameter `arg` has been renamed to `func`, and it "
"will stop being supported in a future version of pandas.",
FutureWarning,
stacklevel=find_stack_level(),
)
else:
raise ValueError("The `func` parameter is required")

if callable(func):
func = functools.partial(func, **kwargs)
new_values = self._map_values(func, na_action=na_action)
return self._constructor(new_values, index=self.index, copy=False).__finalize__(
self, method="map"
)
Expand Down
24 changes: 24 additions & 0 deletions pandas/tests/series/methods/test_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,3 +604,27 @@ def test_map_kwargs():
result = Series([2, 4, 5]).map(lambda x, y: x + y, y=2)
expected = Series([4, 6, 7])
tm.assert_series_equal(result, expected)


def test_map_arg_as_kwarg():
with tm.assert_produces_warning(
FutureWarning, match="`arg` has been renamed to `func`"
):
Series([1, 2]).map(arg={})


def test_map_func_and_arg():
# `arg`is considered a normal kwarg that should be passed to the function
result = Series([1, 2]).map(lambda _, arg: arg, arg=3)
expected = Series([3, 3])
tm.assert_series_equal(result, expected)


def test_map_no_func_or_arg():
with pytest.raises(ValueError, match="The `func` parameter is required"):
Series([1, 2]).map()


def test_map_func_is_none():
with pytest.raises(ValueError, match="The `func` parameter is required"):
Series([1, 2]).map(func=None)
Loading