Repository: pandas-dev/pandas

Issue:
series.agg(np.nansum) etc. returns a  series, scalar expected
```python
>>> pd.Series([1,2,3,4]).agg(np.sum)
10
>>> pd.Series([1,2,3,4]).agg(np.nansum)
0    1
1    2
2    3
3    4
dtype: int64
```
I would expect the return values of ``.agg(np.nansum)`` and ``.agg(np.sum)`` to be the same, given that pandas "normalizes" np.sum into np.nansum (don't know the correct term). 

the same issue is with ``np.nanmean``, ``np.nanmax`` etc.

#### Problem description

The underlying issue is that ``SelectionMixIn._cython_table`` has records for ``np.sum``, ``np.mean`` etc, but not ``np.nansum``, ``np.nanmean`` etc.

From a quick look at it, it seems that the issue is easily fixable, by adding the ``np.nan*`` function to cython_table.

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: 7590b8723516a9d595c287067fa639fbb9e19ec1
python: 3.6.3.final.0
python-bits: 32
OS: Windows
OS-release: 10
machine: AMD64
processor: Intel64 Family 6 Model 78 Stepping 3, GenuineIntel
byteorder: little
LC_ALL: None
LANG: None
LOCALE: None.None

pandas: 0.22.0.dev0+710.g7590b87.dirty
pytest: 3.3.1
pip: 9.0.1
setuptools: 38.2.5
Cython: 0.26.1
numpy: 1.13.3
scipy: 1.0.0
pyarrow: None
xarray: None
IPython: 6.2.1
sphinx: 1.6.3
patsy: 0.4.1
dateutil: 2.6.1
pytz: 2017.3
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: 2.1.0
openpyxl: 2.4.9
xlrd: 1.1.0
xlwt: 1.3.0
xlsxwriter: None
lxml: None
bs4: None
html5lib: 1.0b10
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: 2.9.6
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None

</details>



Discussion:
~~we don't have the nan functions in our _cython_map It think. welcome to a PR~~

I see you said that!
Made an attempt in [this PR](https://github.com/pandas-dev/pandas/pull/19670/files) but couldn't quite get it to work, hopefully somebody else is able to pick this up. I'll try again at a later date if not 😄 

Resolving patch:
diff --git a/pandas/core/base.py b/pandas/core/base.py
--- a/pandas/core/base.py
+++ b/pandas/core/base.py
@@ -178,11 +178,13 @@ class SelectionMixin(object):
     _selection = None
     _internal_names = ['_cache', '__setstate__']
     _internal_names_set = set(_internal_names)
+
     _builtin_table = OrderedDict((
         (builtins.sum, np.sum),
         (builtins.max, np.max),
         (builtins.min, np.min),
     ))
+
     _cython_table = OrderedDict((
         (builtins.sum, 'sum'),
         (builtins.max, 'max'),
@@ -190,15 +192,25 @@ class SelectionMixin(object):
         (np.all, 'all'),
         (np.any, 'any'),
         (np.sum, 'sum'),
+        (np.nansum, 'sum'),
         (np.mean, 'mean'),
+        (np.nanmean, 'mean'),
         (np.prod, 'prod'),
+        (np.nanprod, 'prod'),
         (np.std, 'std'),
+        (np.nanstd, 'std'),
         (np.var, 'var'),
+        (np.nanvar, 'var'),
         (np.median, 'median'),
+        (np.nanmedian, 'median'),
         (np.max, 'max'),
+        (np.nanmax, 'max'),
         (np.min, 'min'),
+        (np.nanmin, 'min'),
         (np.cumprod, 'cumprod'),
+        (np.nancumprod, 'cumprod'),
         (np.cumsum, 'cumsum'),
+        (np.nancumsum, 'cumsum'),
     ))
 
     @property


Test patch:
diff --git a/pandas/tests/groupby/aggregate/test_other.py b/pandas/tests/groupby/aggregate/test_other.py
--- a/pandas/tests/groupby/aggregate/test_other.py
+++ b/pandas/tests/groupby/aggregate/test_other.py
@@ -487,17 +487,6 @@ def test_agg_structs_series(structure, expected):
     tm.assert_series_equal(result, expected)
 
 
-@pytest.mark.parametrize('observed', [
-    True,
-    pytest.param(False,
-                 marks=pytest.mark.xfail(reason="GH#18869: agg func not "
-                                                "called on empty groups.",
-                                         strict=True)),
-    pytest.param(None,
-                 marks=pytest.mark.xfail(reason="GH#18869: agg func not "
-                                                "called on empty groups.",
-                                         strict=True))
-])
 def test_agg_category_nansum(observed):
     categories = ['a', 'b', 'c']
     df = pd.DataFrame({"A": pd.Categorical(['a', 'a', 'b'],