Skip to content

Commit 4118ed8

Browse files
authored
BUG: groupby.apply raising a TypeError when __getitem__ selects multlple columns (#53207)
* BUG: groupby.apply raising a TypeError when __getitem__ selects multiple columns * Fix whatsnew * typing * Typing
1 parent a51af3f commit 4118ed8

File tree

3 files changed

+24
-4
lines changed

3 files changed

+24
-4
lines changed

doc/source/whatsnew/v2.1.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -416,10 +416,10 @@ Groupby/resample/rolling
416416
or :class:`PeriodIndex`, and the ``groupby`` method was given a function as its first argument,
417417
the function operated on the whole index rather than each element of the index. (:issue:`51979`)
418418
- Bug in :meth:`DataFrameGroupBy.apply` causing an error to be raised when the input :class:`DataFrame` was subset as a :class:`DataFrame` after groupby (``[['a']]`` and not ``['a']``) and the given callable returned :class:`Series` that were not all indexed the same. (:issue:`52444`)
419+
- Bug in :meth:`DataFrameGroupBy.apply` raising a ``TypeError`` when selecting multiple columns and providing a function that returns ``np.ndarray`` results (:issue:`18930`)
419420
- Bug in :meth:`GroupBy.groups` with a datetime key in conjunction with another key produced incorrect number of group keys (:issue:`51158`)
420421
- Bug in :meth:`GroupBy.quantile` may implicitly sort the result index with ``sort=False`` (:issue:`53009`)
421422
- Bug in :meth:`GroupBy.var` failing to raise ``TypeError`` when called with datetime64, timedelta64 or :class:`PeriodDtype` values (:issue:`52128`, :issue:`53045`)
422-
-
423423

424424
Reshaping
425425
^^^^^^^^^

pandas/core/groupby/generic.py

+11-3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
CategoricalDtype,
5252
IntervalDtype,
5353
)
54+
from pandas.core.dtypes.inference import is_hashable
5455
from pandas.core.dtypes.missing import (
5556
isna,
5657
notna,
@@ -1540,9 +1541,16 @@ def _wrap_applied_output(
15401541
# fall through to the outer else clause
15411542
# TODO: sure this is right? we used to do this
15421543
# after raising AttributeError above
1543-
return self.obj._constructor_sliced(
1544-
values, index=key_index, name=self._selection
1545-
)
1544+
# GH 18930
1545+
if not is_hashable(self._selection):
1546+
# error: Need type annotation for "name"
1547+
name = tuple(self._selection) # type: ignore[var-annotated, arg-type]
1548+
else:
1549+
# error: Incompatible types in assignment
1550+
# (expression has type "Hashable", variable
1551+
# has type "Tuple[Any, ...]")
1552+
name = self._selection # type: ignore[assignment]
1553+
return self.obj._constructor_sliced(values, index=key_index, name=name)
15461554
elif not isinstance(first_not_none, Series):
15471555
# values are not series or array-like but scalars
15481556
# self._selection not passed through to Series as the

pandas/tests/groupby/test_apply.py

+12
Original file line numberDiff line numberDiff line change
@@ -1404,3 +1404,15 @@ def test_apply_inconsistent_output(group_col):
14041404
)
14051405

14061406
tm.assert_series_equal(result, expected)
1407+
1408+
1409+
def test_apply_array_output_multi_getitem():
1410+
# GH 18930
1411+
df = DataFrame(
1412+
{"A": {"a": 1, "b": 2}, "B": {"a": 1, "b": 2}, "C": {"a": 1, "b": 2}}
1413+
)
1414+
result = df.groupby("A")[["B", "C"]].apply(lambda x: np.array([0]))
1415+
expected = Series(
1416+
[np.array([0])] * 2, index=Index([1, 2], name="A"), name=("B", "C")
1417+
)
1418+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)