Skip to content

Commit

Permalink
CLN: Enforce deprecation get_group with tuples of length 1 (#57743)
Browse files Browse the repository at this point in the history
* CLN: Enforce deprecation get_group with tuples of length 1

* Add in similar deprecation involving iteration

* type ignore
  • Loading branch information
rhshadrach authored Mar 7, 2024
1 parent d447ca6 commit ed91fbe
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 42 deletions.
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v3.0.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,12 @@ Removal of prior version deprecations/changes
- All arguments in :meth:`Series.to_dict` are now keyword only (:issue:`56493`)
- Changed the default value of ``observed`` in :meth:`DataFrame.groupby` and :meth:`Series.groupby` to ``True`` (:issue:`51811`)
- Enforced deprecation disallowing parsing datetimes with mixed time zones unless user passes ``utc=True`` to :func:`to_datetime` (:issue:`57275`)
- Enforced deprecation of :meth:`.DataFrameGroupBy.get_group` and :meth:`.SeriesGroupBy.get_group` allowing the ``name`` argument to be a non-tuple when grouping by a list of length 1 (:issue:`54155`)
- Enforced deprecation of ``axis=None`` acting the same as ``axis=0`` in the DataFrame reductions ``sum``, ``prod``, ``std``, ``var``, and ``sem``, passing ``axis=None`` will now reduce over both axes; this is particularly the case when doing e.g. ``numpy.sum(df)`` (:issue:`21597`)
- Enforced deprecation of passing a dictionary to :meth:`SeriesGroupBy.agg` (:issue:`52268`)
- Enforced silent-downcasting deprecation for :ref:`all relevant methods <whatsnew_220.silent_downcasting>` (:issue:`54710`)
- In :meth:`DataFrame.stack`, the default value of ``future_stack`` is now ``True``; specifying ``False`` will raise a ``FutureWarning`` (:issue:`55448`)
- Iterating over a :class:`.DataFrameGroupBy` or :class:`.SeriesGroupBy` will return tuples of length 1 for the groups when grouping by ``level`` a list of length 1 (:issue:`50064`)
- Methods ``apply``, ``agg``, and ``transform`` will no longer replace NumPy functions (e.g. ``np.sum``) and built-in functions (e.g. ``min``) with the equivalent pandas implementation; use string aliases (e.g. ``"sum"`` and ``"min"``) if you desire to use the pandas implementation (:issue:`53974`)
- Passing both ``freq`` and ``fill_value`` in :meth:`DataFrame.shift` and :meth:`Series.shift` and :meth:`.DataFrameGroupBy.shift` now raises a ``ValueError`` (:issue:`54818`)
- Removed :meth:`.DataFrameGroupBy.quantile` and :meth:`.SeriesGroupBy.quantile` supporting bool dtype (:issue:`53975`)
Expand Down
29 changes: 7 additions & 22 deletions pandas/core/groupby/groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -919,17 +919,9 @@ def get_group(self, name) -> DataFrame | Series:
):
# GH#25971
if isinstance(name, tuple) and len(name) == 1:
# Allow users to pass tuples of length 1 to silence warning
name = name[0]
elif not isinstance(name, tuple):
warnings.warn(
"When grouping with a length-1 list-like, "
"you will need to pass a length-1 tuple to get_group in a future "
"version of pandas. Pass `(name,)` instead of `name` to silence "
"this warning.",
FutureWarning,
stacklevel=find_stack_level(),
)
else:
raise KeyError(name)

inds = self._get_index(name)
if not len(inds):
Expand Down Expand Up @@ -1015,18 +1007,11 @@ def __iter__(self) -> Iterator[tuple[Hashable, NDFrameT]]:
keys = self.keys
level = self.level
result = self._grouper.get_iterator(self._selected_obj)
# error: Argument 1 to "len" has incompatible type "Hashable"; expected "Sized"
if is_list_like(level) and len(level) == 1: # type: ignore[arg-type]
# GH 51583
warnings.warn(
"Creating a Groupby object with a length-1 list-like "
"level parameter will yield indexes as tuples in a future version. "
"To keep indexes as scalars, create Groupby objects with "
"a scalar level parameter instead.",
FutureWarning,
stacklevel=find_stack_level(),
)
if isinstance(keys, list) and len(keys) == 1:
# mypy: Argument 1 to "len" has incompatible type "Hashable"; expected "Sized"
if (
(is_list_like(level) and len(level) == 1) # type: ignore[arg-type]
or (isinstance(keys, list) and len(keys) == 1)
):
# GH#42795 - when keys is a list, return tuples even when length is 1
result = (((key,), group) for key, group in result)
return result
Expand Down
6 changes: 1 addition & 5 deletions pandas/tests/groupby/test_categorical.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,7 @@ def test_level_get_group(observed):
names=["Index1", "Index2"],
),
)
msg = "you will need to pass a length-1 tuple"
with tm.assert_produces_warning(FutureWarning, match=msg):
# GH#25971 - warn when not passing a length-1 tuple
result = g.get_group("a")

result = g.get_group(("a",))
tm.assert_frame_equal(result, expected)


Expand Down
21 changes: 6 additions & 15 deletions pandas/tests/groupby/test_groupby.py
Original file line number Diff line number Diff line change
Expand Up @@ -2529,19 +2529,14 @@ def test_groupby_string_dtype():
@pytest.mark.parametrize(
"level_arg, multiindex", [([0], False), ((0,), False), ([0], True), ((0,), True)]
)
def test_single_element_listlike_level_grouping_deprecation(level_arg, multiindex):
def test_single_element_listlike_level_grouping(level_arg, multiindex):
# GH 51583
df = DataFrame({"a": [1, 2], "b": [3, 4], "c": [5, 6]}, index=["x", "y"])
if multiindex:
df = df.set_index(["a", "b"])
depr_msg = (
"Creating a Groupby object with a length-1 list-like "
"level parameter will yield indexes as tuples in a future version. "
"To keep indexes as scalars, create Groupby objects with "
"a scalar level parameter instead."
)
with tm.assert_produces_warning(FutureWarning, match=depr_msg):
[key for key, _ in df.groupby(level=level_arg)]
result = [key for key, _ in df.groupby(level=level_arg)]
expected = [(1,), (2,)] if multiindex else [("x",), ("y",)]
assert result == expected


@pytest.mark.parametrize("func", ["sum", "cumsum", "cumprod", "prod"])
Expand Down Expand Up @@ -2880,22 +2875,18 @@ def test_groupby_series_with_datetimeindex_month_name():
"kwarg, value, name, warn",
[
("by", "a", 1, None),
("by", ["a"], 1, FutureWarning),
("by", ["a"], (1,), None),
("level", 0, 1, None),
("level", [0], 1, FutureWarning),
("level", [0], (1,), None),
],
)
def test_depr_get_group_len_1_list_likes(test_series, kwarg, value, name, warn):
def test_get_group_len_1_list_likes(test_series, kwarg, value, name, warn):
# GH#25971
obj = DataFrame({"b": [3, 4, 5]}, index=Index([1, 1, 2], name="a"))
if test_series:
obj = obj["b"]
gb = obj.groupby(**{kwarg: value})
msg = "you will need to pass a length-1 tuple"
with tm.assert_produces_warning(warn, match=msg):
result = gb.get_group(name)
result = gb.get_group(name)
if test_series:
expected = Series([3, 4], index=Index([1, 1], name="a"), name="b")
else:
Expand Down

0 comments on commit ed91fbe

Please sign in to comment.