diff --git a/pandas/core/groupby/generic.py b/pandas/core/groupby/generic.py index 8cd727e744519d..8e53972c952759 100644 --- a/pandas/core/groupby/generic.py +++ b/pandas/core/groupby/generic.py @@ -970,6 +970,11 @@ def _cython_agg_blocks(self, how, alt=None, numeric_only=True, min_count=-1): # call our grouper again with only this block obj = self.obj[data.items[locs]] + if obj.shape[1] == 1: + # Avoid call to self.values that can occur in DataFrame + # reductions; see GH#28949 + obj = obj.iloc[:, 0] + s = groupby(obj, self.grouper) try: result = s.aggregate(lambda x: alt(x, axis=self.axis)) @@ -978,17 +983,29 @@ def _cython_agg_blocks(self, how, alt=None, numeric_only=True, min_count=-1): # continue and exclude the block deleted_items.append(locs) continue + + # unwrap DataFrame to get array + assert len(result._data.blocks) == 1 + result = result._data.blocks[0].values + if result.ndim == 1 and isinstance(result, np.ndarray): + result = result.reshape(1, -1) + finally: + assert not isinstance(result, DataFrame) + if result is not no_result: # see if we can cast the block back to the original dtype result = maybe_downcast_numeric(result, block.dtype) - if result.ndim == 1 and isinstance(result, np.ndarray): + if block.is_extension and isinstance(result, np.ndarray): # e.g. block.values was an IntegerArray + # (1, N) case can occur if block.values was Categorical + # and result is ndarray[object] + assert result.ndim == 1 or result.shape[0] == 1 try: # Cast back if feasible result = type(block.values)._from_sequence( - result, dtype=block.values.dtype + result.ravel(), dtype=block.values.dtype ) except ValueError: # reshape to be valid for non-Extension Block diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py index 6f2868482b7986..fa651794698403 100644 --- a/pandas/core/groupby/groupby.py +++ b/pandas/core/groupby/groupby.py @@ -1344,13 +1344,14 @@ def f(self, **kwargs): raise except DataError: pass - except Exception: - # TODO: the remaining test cases that get here are from: - # - AttributeError from _cython_agg_blocks bug passing - # DataFrame to make_block; see GH#28275 - # - TypeError in _cython_operation calling ensure_float64 - # on object array containing complex numbers; - # see test_groupby_complex, test_max_nan_bug + except (TypeError, NotImplementedError): + # TODO: + # - TypeError: this is reached via test_groupby_complex + # and can be fixed by implementing _group_add for + # complex dtypes + # - NotImplementedError: reached in test_max_nan_bug, + # raised in _get_cython_function and should probably + # be handled inside _cython_agg_blocks pass # apply a non-cython aggregation