-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
BUG: Allow non-callable attributes in aggregate function. Fixes GH16405 #16458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -378,7 +378,7 @@ def aggregate(self, func, *args, **kwargs): | |
def _try_aggregate_string_function(self, arg, *args, **kwargs): | ||
""" | ||
if arg is a string, then try to operate on it: | ||
- try to find a function on ourselves | ||
- try to find a function (or attribute) on ourselves | ||
- try to find a numpy function | ||
- raise | ||
|
||
|
@@ -387,7 +387,15 @@ def _try_aggregate_string_function(self, arg, *args, **kwargs): | |
|
||
f = getattr(self, arg, None) | ||
if f is not None: | ||
return f(*args, **kwargs) | ||
if callable(f): | ||
return f(*args, **kwargs) | ||
|
||
# people may try to aggregate on a non-callable attribute | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. blank line |
||
# but don't let them think they can pass args to it | ||
assert len(args) == 0 | ||
assert len([kwarg for kwarg in kwargs | ||
if kwarg not in ['axis', '_level']]) == 0 | ||
return f | ||
|
||
f = getattr(np, arg, None) | ||
if f is not None: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -635,3 +635,46 @@ def test_nuiscance_columns(self): | |
expected = DataFrame([[6, 6., 'foobarbaz']], | ||
index=['sum'], columns=['A', 'B', 'C']) | ||
assert_frame_equal(result, expected) | ||
|
||
def test_non_callable_aggregates(self): | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you add a comment of |
||
# GH 16405 | ||
df = DataFrame({'A': [None, 2, 3], | ||
'B': [1.0, np.nan, 3.0], | ||
'C': ['foo', None, 'bar']}) | ||
|
||
# Function aggregate | ||
result = df.agg({'A': 'count'}) | ||
expected = pd.Series({'A': 2}) | ||
|
||
assert_series_equal(result, expected) | ||
|
||
# Non-function aggregate | ||
result = df.agg({'A': 'size'}) | ||
expected = pd.Series({'A': 3}) | ||
|
||
assert_series_equal(result, expected) | ||
|
||
# Mix function and non-function aggs | ||
result1 = df.agg(['count', 'size']) | ||
result2 = df.agg({'A': ['count', 'size'], | ||
'B': ['count', 'size'], | ||
'C': ['count', 'size']}) | ||
expected = pd.DataFrame({'A': {'count': 2, 'size': 3}, | ||
'B': {'count': 2, 'size': 3}, | ||
'C': {'count': 2, 'size': 3}}) | ||
|
||
assert_frame_equal(result1, result2, check_like=True) | ||
assert_frame_equal(result2, expected, check_like=True) | ||
|
||
# Just functional string arg is same as calling df.arg() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you add a minimal tests to |
||
result = df.agg('count') | ||
expected = df.count() | ||
|
||
assert_series_equal(result, expected) | ||
|
||
# Just a string attribute arg same as calling df.arg | ||
result = df.agg('size') | ||
expected = df.size | ||
|
||
assert result == expected |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DataFrame.agg()
andSeries.agg()