Skip to content

Commit b0a7a0f

Browse files
author
tp
committed
add np.nan funcs to _cython_table
1 parent e033c06 commit b0a7a0f

File tree

3 files changed

+67
-4
lines changed

3 files changed

+67
-4
lines changed

doc/source/whatsnew/v0.23.1.txt

+5
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,8 @@ Categorical
8989
^^^^^^^^^^^
9090

9191
-
92+
93+
Numeric
94+
^^^^^^^
95+
96+
- :meth:`~DataFrame.agg` now correctly handles numpy NaN-aware methods like :meth:`numpy.nansum` (:issue:`19629`)

pandas/core/base.py

+19-4
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
from pandas.core import common as com, algorithms
2323
import pandas.core.nanops as nanops
2424
import pandas._libs.lib as lib
25-
from pandas.compat.numpy import function as nv
25+
from pandas.compat.numpy import (function as nv, _np_version_under1p10,
26+
_np_version_under1p12)
2627
from pandas.compat import PYPY
2728
from pandas.util._decorators import (Appender, cache_readonly,
2829
deprecate_kwarg, Substitution)
@@ -191,17 +192,31 @@ class SelectionMixin(object):
191192
np.all: 'all',
192193
np.any: 'any',
193194
np.sum: 'sum',
195+
np.nansum: 'sum',
194196
np.mean: 'mean',
197+
np.nanmean: 'mean',
195198
np.prod: 'prod',
196199
np.std: 'std',
200+
np.nanstd: 'std',
197201
np.var: 'var',
202+
np.nanvar: 'var',
198203
np.median: 'median',
204+
np.nanmedian: 'median',
199205
np.max: 'max',
206+
np.nanmax: 'max',
200207
np.min: 'min',
208+
np.nanmin: 'min',
201209
np.cumprod: 'cumprod',
202-
np.cumsum: 'cumsum'
210+
np.cumsum: 'cumsum',
203211
}
204212

213+
if not _np_version_under1p10:
214+
_cython_table[np.nanprod] = 'prod'
215+
216+
if not _np_version_under1p12:
217+
_cython_table[np.nancumprod] = 'cumprod'
218+
_cython_table[np.nancumsum] = 'cumsum'
219+
205220
@property
206221
def _selection_name(self):
207222
"""
@@ -553,8 +568,8 @@ def is_any_frame():
553568
result = None
554569

555570
f = self._is_cython_func(arg)
556-
if f and not args and not kwargs:
557-
return getattr(self, f)(), None
571+
if f:
572+
return getattr(self, f)(*args, **kwargs), None
558573

559574
# caller can react
560575
return result, True

pandas/tests/test_nanops.py

+43
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,49 @@ def prng(self):
994994
return np.random.RandomState(1234)
995995

996996

997+
@pytest.fixture(params=[
998+
pd.Series([1, 2, 3, 4, 5, 6]),
999+
pd.DataFrame([[1, 2, 3], [4, 5, 6]])
1000+
])
1001+
def nan_test_object(request):
1002+
return request.param
1003+
1004+
1005+
@pytest.mark.parametrize("standard, nan_method", [
1006+
(np.sum, np.nansum),
1007+
(np.mean, np.nanmean),
1008+
(np.std, np.nanstd),
1009+
(np.var, np.nanvar),
1010+
(np.median, np.nanmedian),
1011+
(np.max, np.nanmax),
1012+
(np.min, np.nanmin),
1013+
])
1014+
def test_np_nan_functions(standard, nan_method, nan_test_object):
1015+
tm.assert_almost_equal(nan_test_object.agg(standard),
1016+
nan_test_object.agg(nan_method),
1017+
check_exact=True)
1018+
1019+
1020+
@td.skip_if_no("numpy", min_version="1.10.0")
1021+
def test_np_nanprod(nan_test_object):
1022+
tm.assert_almost_equal(nan_test_object.agg(np.prod),
1023+
nan_test_object.agg(np.nanprod),
1024+
check_exact=True)
1025+
1026+
1027+
@td.skip_if_no("numpy", min_version="1.12.0")
1028+
def test_np_nancumprod(nan_test_object):
1029+
# Not using pytest params for methods as will fail at build time
1030+
methods = [
1031+
(np.cumprod, np.nancumprod),
1032+
(np.cumsum, np.nancumsum)
1033+
]
1034+
for standard, nan_method in methods:
1035+
tm.assert_almost_equal(nan_test_object.agg(standard),
1036+
nan_test_object.agg(nan_method),
1037+
check_exact=True)
1038+
1039+
9971040
def test_use_bottleneck():
9981041

9991042
if nanops._BOTTLENECK_INSTALLED:

0 commit comments

Comments
 (0)