diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index b6bd86bd79a1f..60a9d4435e86c 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -597,6 +597,7 @@ Groupby/Resample/Rolling - Bug in :func:`infer_freq` causing indices with 2-day gaps during the working week to be wrongly inferred as business daily (:issue:`16624`) - Bug in ``.rolling(...).quantile()`` which incorrectly used different defaults than :func:`Series.quantile()` and :func:`DataFrame.quantile()` (:issue:`9413`, :issue:`16211`) - Bug in ``groupby.transform()`` that would coerce boolean dtypes back to float (:issue:`16875`) +- Bug in ``Grouper.aggregate()`` where grouping by a vector of mixed types would raise a ``TypeError`` only if the aggregating function returned a list-like object (:issue:`16916`) - Bug in ``Series.resample(...).apply()`` where an empty ``Series`` modified the source index and did not return the name of a ``Series`` (:issue:`14313`) - Bug in ``.rolling(...).apply(...)`` with a ``DataFrame`` with a ``DatetimeIndex``, a ``window`` of a timedelta-convertible and ``min_periods >= 1` (:issue:`15305`) - Bug in ``DataFrame.groupby`` where index and column keys were not recognized correctly when the number of keys equaled the number of elements on the groupby axis (:issue:`16859`) diff --git a/pandas/core/groupby.py b/pandas/core/groupby.py index a62ae40a85941..a0e842d308d8a 100644 --- a/pandas/core/groupby.py +++ b/pandas/core/groupby.py @@ -59,6 +59,7 @@ from pandas.io.formats.printing import pprint_thing from pandas.util._validators import validate_kwargs +from pandas.core.sorting import safe_sort import pandas.core.algorithms as algorithms import pandas.core.common as com from pandas.core.config import option_context @@ -2897,7 +2898,7 @@ def aggregate(self, func_or_funcs, *args, **kwargs): except Exception: result = self._aggregate_named(func_or_funcs, *args, **kwargs) - index = Index(sorted(result), name=self.grouper.names[0]) + index = Index(safe_sort(result), name=self.grouper.names[0]) ret = Series(result, index=index) if not self.as_index: # pragma: no cover diff --git a/pandas/tests/groupby/test_aggregate.py b/pandas/tests/groupby/test_aggregate.py index efc833575843c..daa78f2ec79d8 100644 --- a/pandas/tests/groupby/test_aggregate.py +++ b/pandas/tests/groupby/test_aggregate.py @@ -892,3 +892,17 @@ def test_sum_uint64_overflow(self): expected.index.name = 0 result = df.groupby(0).sum() tm.assert_frame_equal(result, expected) + + def test_mixed_type_grouping(self): + # see gh-19616 + expected = pd.DataFrame(data=[[[1, 1], [2, 2], [3, 3]], + [[1, 1], [2, 2], [3, 3]]], + columns=['X', 'Y', 'Z'], + index=pd.Index(data=[2, 'g1'], + name='grouping')) + + df = pd.DataFrame(data=[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]], + columns=list('XYZ'), index=list('qwer')) + df['grouping'] = ['g1', 'g1', 2, 2] + result = df.groupby('grouping').aggregate(lambda x: x.tolist()) + tm.assert_frame_equal(result, expected)