pandas-dev/pandas · error · TypeError

Categorical is not ordered for operation {op} you can use .a

Error message

Categorical is not ordered for operation {op}
you can use .as_ordered() to change the Categorical to an ordered one

What it means

Raised by Categorical.check_for_ordered when an operation that requires a total ordering (min, max, median, comparison, argsort with ordering) is applied to an unordered Categorical. Unordered categoricals define labels only, not magnitude, so min/max/median are undefined and pandas refuses to pick an arbitrary answer. The message directs you to .as_ordered() to promote ordering. This guard sits inside every order-sensitive method on Categorical.

Source

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

            categorical.categories.dtype.
        """
        # if we are a datetime and period index, return Index to keep metadata
        if needs_i8_conversion(self.categories.dtype):
            return self.categories.take(
                self._codes, allow_fill=True, fill_value=NaT
            )._values
        elif is_integer_dtype(self.categories.dtype) and -1 in self._codes:
            return (
                self.categories.astype("object")
                .take(self._codes, allow_fill=True, fill_value=np.nan)
                ._values
            )
        return np.array(self)

    def check_for_ordered(self, op) -> None:
        """assert that we are ordered"""
        if not self.ordered:
            raise TypeError(
                f"Categorical is not ordered for operation {op}\n"
                "you can use .as_ordered() to change the "
                "Categorical to an ordered one\n"
            )

    def argsort(
        self, *, ascending: bool = True, kind: SortKind = "quicksort", **kwargs
    ) -> npt.NDArray[np.intp]:
        """
        Return the indices that would sort the Categorical.

        Missing values are sorted at the end.

        Parameters
        ----------
        ascending : bool, default True
            Whether the indices should result in an ascending
            or descending sort.

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Call .cat.as_ordered() (or pd.Categorical(data, categories=[...], ordered=True)) so the categories carry a defined order.
  2. Use .astype(categories_dtype) to operate on the raw values instead of the categorical if order is not meaningful.
  3. Recreate the Categorical with an explicit ordered categories list matching the intended ranking.

Example fix

// before
s = pd.Series(pd.Categorical(['low','high','med']))
s.min()  # TypeError: Categorical is not ordered

// after
s = s.cat.as_ordered()
s.min()  # 'high' -> actually 'low' given default alpha sort; use explicit categories
s = pd.Series(pd.Categorical(['low','med','high'], categories=['low','med','high'], ordered=True))
s.min()  # 'low'
Defensive patterns

Strategy: validation

Validate before calling

def ensure_ordered(s):
    import pandas as pd
    if isinstance(s.dtype, pd.CategoricalDtype) and not s.cat.ordered:
        return s.cat.as_ordered()
    return s

Type guard

import pandas as pd
from typing import Any

def is_ordered_categorical(obj: Any) -> bool:
    dt = getattr(obj, 'dtype', None)
    return isinstance(dt, pd.CategoricalDtype) and dt.ordered

Try / catch

try:
    s.min()
except TypeError as e:
    if 'not ordered for operation' in str(e):
        s = s.cat.as_ordered()
    else:
        raise

Prevention

When it happens

Trigger: Calling .min(), .max(), .median(), .quantile(), or comparison ops (<, >) on an unordered Categorical/Series; calling .argsort() semantics that rely on order; or groupby aggregations like groupby('col')['cat'].min() on an unordered category.

Common situations: Default pd.Categorical(...) is created unordered, so users hit this immediately when computing min/max on a column they intended to be ordinal (e.g. 'low','med','high' or 'cold','warm','hot'). Also common after read_csv with dtype='category' which produces unordered categories.

Related errors


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