From 48d73d8762e1f033142ede52b9a5545e668fa6e7 Mon Sep 17 00:00:00 2001 From: Florian Wilhelm Date: Thu, 22 Jun 2017 20:05:21 +0200 Subject: [PATCH 1/5] Fix issue 16741 --- pandas/_libs/src/reduce.pyx | 3 +-- pandas/tests/groupby/test_aggregate.py | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pandas/_libs/src/reduce.pyx b/pandas/_libs/src/reduce.pyx index 2bba07256305a..66c72b5206e40 100644 --- a/pandas/_libs/src/reduce.pyx +++ b/pandas/_libs/src/reduce.pyx @@ -395,7 +395,6 @@ cdef class SeriesGrouper: result = _get_result_array(res, self.ngroups, len(self.dummy_arr)) - util.assign_value_1d(result, lab, res) counts[lab] = group_size islider.advance(group_size) @@ -419,7 +418,7 @@ cdef class SeriesGrouper: cdef inline _extract_result(object res): """ extract the result object, it might be a 0-dim ndarray or a len-1 0-dim, or a scalar """ - if hasattr(res, 'values'): + if hasattr(res, 'values') and isinstance(res.values, np.ndarray): res = res.values if not np.isscalar(res): if isinstance(res, np.ndarray): diff --git a/pandas/tests/groupby/test_aggregate.py b/pandas/tests/groupby/test_aggregate.py index b578a6efb0034..e3e417ff005ef 100644 --- a/pandas/tests/groupby/test_aggregate.py +++ b/pandas/tests/groupby/test_aggregate.py @@ -882,3 +882,7 @@ def test_sum_uint64_overflow(self): expected.index.name = 0 result = df.groupby(0).sum() tm.assert_frame_equal(result, expected) + + def test_agg_ret_dict(self): + ts = self.df.groupby('A')['B'].agg(lambda x: x.value_counts().to_dict()) + assert isinstance(ts.loc['foo'], dict) From 8fcb2167e016d5f91fb8ea5943c4b28197826bd7 Mon Sep 17 00:00:00 2001 From: Florian Wilhelm Date: Thu, 22 Jun 2017 20:46:35 +0200 Subject: [PATCH 2/5] Changed name of unit test --- pandas/tests/groupby/test_aggregate.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pandas/tests/groupby/test_aggregate.py b/pandas/tests/groupby/test_aggregate.py index e3e417ff005ef..baf59068352a0 100644 --- a/pandas/tests/groupby/test_aggregate.py +++ b/pandas/tests/groupby/test_aggregate.py @@ -611,6 +611,11 @@ def test_cython_agg_frame_columns(self): df.groupby(level=0, axis='columns').mean() df.groupby(level=0, axis='columns').mean() + def test_cython_agg_return_dict(self): + ts = self.df.groupby('A')['B'].agg(lambda x: x.value_counts().to_dict()) + assert isinstance(ts.loc['foo'], dict) + + def test_cython_fail_agg(self): dr = bdate_range('1/1/2000', periods=50) ts = Series(['A', 'B', 'C', 'D', 'E'] * 10, index=dr) @@ -882,7 +887,3 @@ def test_sum_uint64_overflow(self): expected.index.name = 0 result = df.groupby(0).sum() tm.assert_frame_equal(result, expected) - - def test_agg_ret_dict(self): - ts = self.df.groupby('A')['B'].agg(lambda x: x.value_counts().to_dict()) - assert isinstance(ts.loc['foo'], dict) From 0fd94fb73ad3aab1ecb0a50fcea519a68c7ffdd2 Mon Sep 17 00:00:00 2001 From: Florian Wilhelm Date: Thu, 22 Jun 2017 20:52:57 +0200 Subject: [PATCH 3/5] Added whatsnew entry --- doc/source/whatsnew/v0.21.0.txt | 2 ++ pandas/tests/groupby/test_aggregate.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index 9d330cf3fdf2d..7f0c4ffa55767 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -90,6 +90,8 @@ Performance Improvements Bug Fixes ~~~~~~~~~ +- Fixes regression in 0.20, `aggregate` allows dictionaries as return values again (:issue:`16741`) + Conversion ^^^^^^^^^^ diff --git a/pandas/tests/groupby/test_aggregate.py b/pandas/tests/groupby/test_aggregate.py index baf59068352a0..4bfb74d574a8f 100644 --- a/pandas/tests/groupby/test_aggregate.py +++ b/pandas/tests/groupby/test_aggregate.py @@ -612,10 +612,10 @@ def test_cython_agg_frame_columns(self): df.groupby(level=0, axis='columns').mean() def test_cython_agg_return_dict(self): - ts = self.df.groupby('A')['B'].agg(lambda x: x.value_counts().to_dict()) + ts = self.df.groupby('A')['B'].agg( + lambda x: x.value_counts().to_dict()) assert isinstance(ts.loc['foo'], dict) - def test_cython_fail_agg(self): dr = bdate_range('1/1/2000', periods=50) ts = Series(['A', 'B', 'C', 'D', 'E'] * 10, index=dr) From 946aa60aa4a387c1a389de4ce52198af7883690d Mon Sep 17 00:00:00 2001 From: Florian Wilhelm Date: Fri, 23 Jun 2017 08:06:33 +0200 Subject: [PATCH 4/5] Added empty line again --- pandas/_libs/src/reduce.pyx | 1 + 1 file changed, 1 insertion(+) diff --git a/pandas/_libs/src/reduce.pyx b/pandas/_libs/src/reduce.pyx index 66c72b5206e40..3ce94022e586b 100644 --- a/pandas/_libs/src/reduce.pyx +++ b/pandas/_libs/src/reduce.pyx @@ -395,6 +395,7 @@ cdef class SeriesGrouper: result = _get_result_array(res, self.ngroups, len(self.dummy_arr)) + util.assign_value_1d(result, lab, res) counts[lab] = group_size islider.advance(group_size) From aac033189f341f2fa5a8feddafbd974ac919205a Mon Sep 17 00:00:00 2001 From: Florian Wilhelm Date: Wed, 28 Jun 2017 22:25:50 +0200 Subject: [PATCH 5/5] Fixed code review remarks --- doc/source/whatsnew/v0.21.0.txt | 2 +- pandas/tests/groupby/test_aggregate.py | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index 7f0c4ffa55767..36b1cb7b6d5c5 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -90,7 +90,7 @@ Performance Improvements Bug Fixes ~~~~~~~~~ -- Fixes regression in 0.20, `aggregate` allows dictionaries as return values again (:issue:`16741`) +- Fixes regression in 0.20, :func:`Series.aggregate` and :func:`DataFrame.aggregate` allow dictionaries as return values again (:issue:`16741`) Conversion ^^^^^^^^^^ diff --git a/pandas/tests/groupby/test_aggregate.py b/pandas/tests/groupby/test_aggregate.py index 4bfb74d574a8f..efc833575843c 100644 --- a/pandas/tests/groupby/test_aggregate.py +++ b/pandas/tests/groupby/test_aggregate.py @@ -612,9 +612,14 @@ def test_cython_agg_frame_columns(self): df.groupby(level=0, axis='columns').mean() def test_cython_agg_return_dict(self): + # GH 16741 ts = self.df.groupby('A')['B'].agg( lambda x: x.value_counts().to_dict()) - assert isinstance(ts.loc['foo'], dict) + expected = Series([{'two': 1, 'one': 1, 'three': 1}, + {'two': 2, 'one': 2, 'three': 1}], + index=Index(['bar', 'foo'], name='A'), + name='B') + assert_series_equal(ts, expected) def test_cython_fail_agg(self): dr = bdate_range('1/1/2000', periods=50)