From 96b428dfee017be59d0319501054db8fc9ab42ff Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Tue, 22 Oct 2019 10:28:07 -0700 Subject: [PATCH] REF: avoid getattr pattern for groupby-rank functions --- pandas/_libs/groupby.pyx | 20 -------------------- pandas/core/groupby/ops.py | 14 +++++++++++--- pandas/tests/groupby/test_rank.py | 3 ++- 3 files changed, 13 insertions(+), 24 deletions(-) diff --git a/pandas/_libs/groupby.pyx b/pandas/_libs/groupby.pyx index c21528a7082f6..b2ffbb3ecb4f2 100644 --- a/pandas/_libs/groupby.pyx +++ b/pandas/_libs/groupby.pyx @@ -923,12 +923,6 @@ def group_last(rank_t[:, :] out, raise RuntimeError("empty group with uint64_t") -group_last_float64 = group_last["float64_t"] -group_last_float32 = group_last["float32_t"] -group_last_int64 = group_last["int64_t"] -group_last_object = group_last["object"] - - @cython.wraparound(False) @cython.boundscheck(False) def group_nth(rank_t[:, :] out, @@ -1020,12 +1014,6 @@ def group_nth(rank_t[:, :] out, raise RuntimeError("empty group with uint64_t") -group_nth_float64 = group_nth["float64_t"] -group_nth_float32 = group_nth["float32_t"] -group_nth_int64 = group_nth["int64_t"] -group_nth_object = group_nth["object"] - - @cython.boundscheck(False) @cython.wraparound(False) def group_rank(float64_t[:, :] out, @@ -1213,14 +1201,6 @@ def group_rank(float64_t[:, :] out, out[i, 0] = out[i, 0] / grp_sizes[i, 0] -group_rank_float64 = group_rank["float64_t"] -group_rank_float32 = group_rank["float32_t"] -group_rank_int64 = group_rank["int64_t"] -group_rank_uint64 = group_rank["uint64_t"] -# Note: we do not have a group_rank_object because that would require a -# not-nogil implementation, see GH#19560 - - # ---------------------------------------------------------------------- # group_min, group_max # ---------------------------------------------------------------------- diff --git a/pandas/core/groupby/ops.py b/pandas/core/groupby/ops.py index fcc646dec89d9..00e7012b40986 100644 --- a/pandas/core/groupby/ops.py +++ b/pandas/core/groupby/ops.py @@ -419,13 +419,21 @@ def get_func(fname): # otherwise find dtype-specific version, falling back to object for dt in [dtype_str, "object"]: - f = getattr( + f2 = getattr( libgroupby, "{fname}_{dtype_str}".format(fname=fname, dtype_str=dt), None, ) - if f is not None: - return f + if f2 is not None: + return f2 + + if hasattr(f, "__signatures__"): + # inspect what fused types are implemented + if dtype_str == "object" and "object" not in f.__signatures__: + # return None so we get a NotImplementedError below + # instead of a TypeError at runtime + return None + return f ftype = self._cython_functions[kind][how] diff --git a/pandas/tests/groupby/test_rank.py b/pandas/tests/groupby/test_rank.py index a6ea793b53c41..e407cfadac2fb 100644 --- a/pandas/tests/groupby/test_rank.py +++ b/pandas/tests/groupby/test_rank.py @@ -3,6 +3,7 @@ import pandas as pd from pandas import DataFrame, Series, concat +from pandas.core.base import DataError from pandas.util import testing as tm @@ -384,7 +385,7 @@ def test_rank_avg_even_vals(): def test_rank_object_raises(ties_method, ascending, na_option, pct, vals): df = DataFrame({"key": ["foo"] * 5, "val": vals}) - with pytest.raises(TypeError, match="not callable"): + with pytest.raises(DataError, match="No numeric types to aggregate"): df.groupby("key").rank( method=ties_method, ascending=ascending, na_option=na_option, pct=pct )