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
- Call .cat.as_ordered() (or pd.Categorical(data, categories=[...], ordered=True)) so the categories carry a defined order.
- Use .astype(categories_dtype) to operate on the raw values instead of the categorical if order is not meaningful.
- 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
- Create ordinal labels with pd.Categorical(data, categories=[...], ordered=True).
- Guard min/max/median/rank calls behind an ordered check for category columns.
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
- 'values' is not ordered, please explicitly specify the categ
- Cannot perform {how} with non-ordered Categorical
- Lengths must match.
- Unordered Categoricals can only compare equality or not
- Categoricals can only be compared if 'categories' are the sa
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/9643e0caa308d25d.
Report an issue: GitHub.