Skip to content

Commit 1d99270

Browse files
committed
Raise error in certain unimplemented aggregation cases.
1 parent 46c52e2 commit 1d99270

File tree

10 files changed

+47
-21
lines changed

10 files changed

+47
-21
lines changed

doc/source/whatsnew/v0.15.1.txt

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Enhancements
3030

3131
- Qualify memory usage in ``DataFrame.info()`` by adding ``+`` if it is a lower bound (:issue:`8578`)
3232

33+
- Raise errors in certain aggregation cases where an argument such as ``numeric_only`` is not handled (:issue:`8592`).
34+
3335

3436
.. _whatsnew_0151.performance:
3537

pandas/core/categorical.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1210,8 +1210,8 @@ def __setitem__(self, key, value):
12101210
self._codes[key] = lindexer
12111211

12121212
#### reduction ops ####
1213-
def _reduce(self, op, axis=0, skipna=True, numeric_only=None,
1214-
filter_type=None, name=None, **kwds):
1213+
def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
1214+
filter_type=None, **kwds):
12151215
""" perform the reduction type operation """
12161216
func = getattr(self,name,None)
12171217
if func is None:

pandas/core/frame.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -4129,7 +4129,7 @@ def any(self, axis=None, bool_only=None, skipna=True, level=None,
41294129
if level is not None:
41304130
return self._agg_by_level('any', axis=axis, level=level,
41314131
skipna=skipna)
4132-
return self._reduce(nanops.nanany, axis=axis, skipna=skipna,
4132+
return self._reduce(nanops.nanany, 'any', axis=axis, skipna=skipna,
41334133
numeric_only=bool_only, filter_type='bool')
41344134

41354135
def all(self, axis=None, bool_only=None, skipna=True, level=None,
@@ -4160,11 +4160,11 @@ def all(self, axis=None, bool_only=None, skipna=True, level=None,
41604160
if level is not None:
41614161
return self._agg_by_level('all', axis=axis, level=level,
41624162
skipna=skipna)
4163-
return self._reduce(nanops.nanall, axis=axis, skipna=skipna,
4163+
return self._reduce(nanops.nanall, 'all', axis=axis, skipna=skipna,
41644164
numeric_only=bool_only, filter_type='bool')
41654165

4166-
def _reduce(self, op, axis=0, skipna=True, numeric_only=None,
4167-
filter_type=None, name=None, **kwds):
4166+
def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
4167+
filter_type=None, **kwds):
41684168
axis = self._get_axis_number(axis)
41694169
f = lambda x: op(x, axis=axis, skipna=skipna, **kwds)
41704170
labels = self._get_agg_axis(axis)

pandas/core/generic.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -3934,9 +3934,8 @@ def stat_func(self, axis=None, skipna=None, level=None,
39343934
if level is not None:
39353935
return self._agg_by_level(name, axis=axis, level=level,
39363936
skipna=skipna)
3937-
return self._reduce(f, axis=axis,
3938-
skipna=skipna, numeric_only=numeric_only,
3939-
name=name)
3937+
return self._reduce(f, name, axis=axis,
3938+
skipna=skipna, numeric_only=numeric_only)
39403939
stat_func.__name__ = name
39413940
return stat_func
39423941

@@ -4005,7 +4004,7 @@ def stat_func(self, axis=None, skipna=None, level=None, ddof=1,
40054004
if level is not None:
40064005
return self._agg_by_level(name, axis=axis, level=level,
40074006
skipna=skipna, ddof=ddof)
4008-
return self._reduce(f, axis=axis,
4007+
return self._reduce(f, name, axis=axis,
40094008
skipna=skipna, ddof=ddof)
40104009
stat_func.__name__ = name
40114010
return stat_func

pandas/core/panel.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -1045,8 +1045,12 @@ def _apply_2d(self, func, axis):
10451045

10461046
return self._construct_return_type(dict(results))
10471047

1048-
def _reduce(self, op, axis=0, skipna=True, numeric_only=None,
1049-
filter_type=None, name=None, **kwds):
1048+
def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
1049+
filter_type=None, **kwds):
1050+
if numeric_only:
1051+
raise NotImplementedError(
1052+
'Panel.{0} does not implement numeric_only.'.format(name))
1053+
10501054
axis_name = self._get_axis_name(axis)
10511055
axis_number = self._get_axis_number(axis_name)
10521056
f = lambda x: op(x, axis=axis_number, skipna=skipna, **kwds)

pandas/core/series.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -2056,8 +2056,8 @@ def apply(self, func, convert_dtype=True, args=(), **kwds):
20562056
return self._constructor(mapped,
20572057
index=self.index).__finalize__(self)
20582058

2059-
def _reduce(self, op, axis=0, skipna=True, numeric_only=None,
2060-
filter_type=None, name=None, **kwds):
2059+
def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
2060+
filter_type=None, **kwds):
20612061
"""
20622062
perform a reduction operation
20632063
@@ -2067,10 +2067,16 @@ def _reduce(self, op, axis=0, skipna=True, numeric_only=None,
20672067
"""
20682068
delegate = self.values
20692069
if isinstance(delegate, np.ndarray):
2070+
# Validate that 'axis' is consistent with Series's single axis.
2071+
self._get_axis_number(axis)
2072+
if numeric_only:
2073+
raise NotImplementedError(
2074+
'Series.{0} does not implement numeric_only.'.format(name))
20702075
return op(delegate, skipna=skipna, **kwds)
20712076

2072-
return delegate._reduce(op=op, axis=axis, skipna=skipna, numeric_only=numeric_only,
2073-
filter_type=filter_type, name=name, **kwds)
2077+
return delegate._reduce(op=op, name=name, axis=axis, skipna=skipna,
2078+
numeric_only=numeric_only,
2079+
filter_type=filter_type, **kwds)
20742080

20752081
def _maybe_box(self, func, dropna=False):
20762082
"""

pandas/sparse/series.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,8 @@ def __array_finalize__(self, obj):
303303
self.name = getattr(obj, 'name', None)
304304
self.fill_value = getattr(obj, 'fill_value', None)
305305

306-
def _reduce(self, op, axis=0, skipna=True, numeric_only=None,
307-
filter_type=None, name=None, **kwds):
306+
def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
307+
filter_type=None, **kwds):
308308
""" perform a reduction operation """
309309
return op(self.get_values(), skipna=skipna, **kwds)
310310

pandas/tests/test_groupby.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1669,11 +1669,11 @@ def test_groupby_multiple_key(self):
16691669
lambda x: x.month,
16701670
lambda x: x.day], axis=1)
16711671

1672-
agged = grouped.agg(lambda x: x.sum(1))
1672+
agged = grouped.agg(lambda x: x.sum())
16731673
self.assertTrue(agged.index.equals(df.columns))
16741674
assert_almost_equal(df.T.values, agged.values)
16751675

1676-
agged = grouped.agg(lambda x: x.sum(1))
1676+
agged = grouped.agg(lambda x: x.sum())
16771677
assert_almost_equal(df.T.values, agged.values)
16781678

16791679
def test_groupby_multi_corner(self):
@@ -1708,7 +1708,7 @@ def test_omit_nuisance(self):
17081708
# won't work with axis = 1
17091709
grouped = df.groupby({'A': 0, 'C': 0, 'D': 1, 'E': 1}, axis=1)
17101710
result = self.assertRaises(TypeError, grouped.agg,
1711-
lambda x: x.sum(1, numeric_only=False))
1711+
lambda x: x.sum(0, numeric_only=False))
17121712

17131713
def test_omit_nuisance_python_multiple(self):
17141714
grouped = self.three_group.groupby(['A', 'B'])

pandas/tests/test_panel.py

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# pylint: disable=W0612,E1101
22

33
from datetime import datetime
4+
from inspect import getargspec
45
import operator
56
import nose
67

@@ -169,6 +170,11 @@ def wrapper(x):
169170

170171
self.assertRaises(Exception, f, axis=obj.ndim)
171172

173+
# Unimplemented numeric_only parameter.
174+
if 'numeric_only' in getargspec(f).args:
175+
self.assertRaisesRegexp(NotImplementedError, name, f,
176+
numeric_only=True)
177+
172178

173179
class SafeForSparse(object):
174180
_multiprocess_can_split_ = True

pandas/tests/test_series.py

+9
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from datetime import datetime, timedelta
66
import operator
77
import string
8+
from inspect import getargspec
89
from itertools import product, starmap
910
from distutils.version import LooseVersion
1011

@@ -2338,6 +2339,14 @@ def testit():
23382339
exp = alternate(s)
23392340
self.assertEqual(res, exp)
23402341

2342+
# Invalid axis.
2343+
self.assertRaises(ValueError, f, self.series, axis=1)
2344+
2345+
# Unimplemented numeric_only parameter.
2346+
if 'numeric_only' in getargspec(f).args:
2347+
self.assertRaisesRegexp(NotImplementedError, name, f,
2348+
self.series, numeric_only=True)
2349+
23412350
testit()
23422351

23432352
try:

0 commit comments

Comments
 (0)