pandas-dev/pandas · error · TypeError

Object with dtype {self.dtype} cannot perform the numpy op {

Error message

Object with dtype {self.dtype} cannot perform the numpy op {ufunc.__name__}

What it means

Raised by Categorical.__array_ufunc__ when a numpy ufunc cannot be dispatched to a dunder operation, an out= reduction, or a reduce. Categorical is a categorical-codes array, so most numpy elementwise ufuncs (e.g. np.add, np.multiply on the category values) have no meaningful definition and pandas refuses to silently broadcast over codes. This is the final fallback after every dispatch attempt returns NotImplemented. It exists to prevent silent, semantically wrong results from treating integer codes as data.

Source

Thrown at pandas/core/arrays/categorical.py:1822

            return result

        if "out" in kwargs:
            # e.g. test_numpy_ufuncs_out
            return arraylike.dispatch_ufunc_with_out(
                self, ufunc, method, *inputs, **kwargs
            )

        if method == "reduce":
            # e.g. TestCategoricalAnalytics::test_min_max_ordered
            result = arraylike.dispatch_reduction_ufunc(
                self, ufunc, method, *inputs, **kwargs
            )
            if result is not NotImplemented:
                return result

        # for all other cases, raise for now (similarly as what happens in
        # Series.__array_prepare__)
        raise TypeError(
            f"Object with dtype {self.dtype} cannot perform "
            f"the numpy op {ufunc.__name__}"
        )

    def __setstate__(self, state) -> None:
        """Necessary for making this object picklable"""
        if not isinstance(state, dict):
            return super().__setstate__(state)

        if "_dtype" not in state:
            state["_dtype"] = CategoricalDtype(state["_categories"], state["_ordered"])

        if "_codes" in state and "_ndarray" not in state:
            # backward compat, changed what is property vs attribute
            state["_ndarray"] = state.pop("_codes")

        super().__setstate__(state)

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Convert the categorical to its underlying values with .astype(categories.dtype) or cat.to_numpy() before applying the numpy ufunc.
  2. Use the .cat.codes accessor if you genuinely want integer-code semantics.
  3. Replace the numpy ufunc with the equivalent pandas/Series method (e.g. Series.add, Series.eq) which dispatches correctly.

Example fix

// before
import numpy as np
cat = pd.Categorical(["a","b","c"])
np.add(cat, 1)  # TypeError

// after
cat.to_numpy()  # array(['a','b','c'], dtype=object)
Defensive patterns

Strategy: type-guard

Validate before calling

def safe_ufunc(cat, ufunc, *args, **kwargs):
    import pandas as pd
    if isinstance(cat.dtype, pd.CategoricalDtype):
        raise TypeError(f"ufunc {ufunc.__name__} not defined on Categorical; convert first")
    return ufunc(cat, *args, **kwargs)

Type guard

import pandas as pd
from typing import Any

def is_categorical(obj: Any) -> bool:
    return isinstance(getattr(obj, 'dtype', None), pd.CategoricalDtype)

Try / catch

try:
    np.add(cat, 1)
except TypeError as e:
    if 'cannot perform the numpy op' in str(e):
        result = np.add(cat.to_numpy(), 1)
    else:
        raise

Prevention

When it happens

Trigger: Calling a numpy ufunc directly on a Categorical or a Series/Index backed by one where no dunder-op dispatch exists: np.add(cat, 1), np.sin(cat), np.logical_and(cat, cat), or np.ufunc.reduce variants that are not min/max/sum-style reductions pandas knows how to handle. Also triggered via np.array(...) coercion paths that route through __array_ufunc__.

Common situations: Passing a categorical Series into a numeric numpy routine during feature engineering, calling np.where on a categorical mask, applying sklearn/numpy pipelines that assume numeric arrays, or upgrading numpy versions where new ufunc dispatch paths surface this guard.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/2ea9c9403da13758. Report an issue: GitHub.