pandas-dev/pandas · error · TypeError
'values' is not ordered, please explicitly specify the…
Error message
'values' is not ordered, please explicitly specify the categories order by passing in a categories argument.
What it means
Raised during category inference in `__init__` when `dtype.ordered=True` but `factorize(values, sort=True)` raised `TypeError` (the values are not sortable, e.g. mixed incompatible types) and the fallback `factorize(sort=False)` succeeded. Because an ordered categorical requires a well-defined sort order, pandas asks the caller to supply an explicit `categories` sequence defining that order.
Solutions
- Provide an explicit ordered category list: `pd.Categorical(values, categories=[...], ordered=True)`.
- Clean/coerce the values to a single sortable dtype before construction.
- Drop `ordered=True` if a total order is not actually required.
- Pre-sort the unique values yourself and pass them as `categories`.
Example fix
# before
import pandas as pd
cat = pd.Categorical(['a', 1, 'b'], ordered=True) # TypeError
# after
cat = pd.Categorical(
['a', 1, 'b'],
categories=['a', 'b', 1], # explicit order
ordered=True,
) Defensive patterns
Strategy: validation
Validate before calling
def ordered_categorical(values, categories=None):
if categories is None:
import pandas as pd
uniq = pd.unique([v for v in values if v is not None])
try:
uniq = sorted(uniq)
except TypeError as e:
raise TypeError(
'values are not sortable; pass categories= explicitly'
) from e
categories = uniq
return pd.Categorical(values, categories=categories, ordered=True) Type guard
def is_sortable(values) -> bool:
try:
sorted(values)
return True
except TypeError:
return False Try / catch
try:
cat = pd.Categorical(values, ordered=True)
except TypeError as e:
if 'is not ordered' in str(e):
cat = pd.Categorical(values, categories=sorted(set(values)), ordered=True)
else:
raise Prevention
- Always pass `categories=[...]` when constructing an ordered Categorical from untrusted/mixed-type data.
- Coerce the values to a single sortable dtype before construction.
- Drop `ordered=True` if you do not actually need a total order.
When it happens
Trigger: Constructing `pd.Categorical(values, ordered=True)` where `values` contains heterogeneous/unorderable types (e.g. `['a', 1, None]`), or unorderable objects whose `__lt__` raises.
Common situations: Loading messy CSV columns with mixed dtypes; building ordered categoricals from object columns that contain a few stray numeric/None entries; user-defined classes without a total order.
Related errors
- Categorical input must be list-like
- Unordered Categoricals can only compare equality or not
- > 1 ndim Categorical are not supported at this time
- Cannot compare a Categorical for op
- Cannot setitem on a Categorical with a new category
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/bc7a089d697d1846.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/categorical.py:485
categories = arr.dictionary.to_pandas(types_mapper=ArrowDtype)
codes = arr.indices.to_numpy()
dtype = CategoricalDtype(categories, values.dtype.pyarrow_dtype.ordered)
else:
preserve_object = False
if isinstance(values, (ABCIndex, ABCSeries)) and values.dtype == object:
# GH#61778
preserve_object = True
if not isinstance(values, ABCIndex):
# in particular RangeIndex xref test_index_equal_range_categories
values = sanitize_array(values, None)
try:
codes, categories = factorize(values, sort=True)
except TypeError as err:
codes, categories = factorize(values, sort=False)
if dtype.ordered:
# raise, as we don't have a sortable data structure and so
# the user should give us one by specifying categories
raise TypeError(
"'values' is not ordered, please "
"explicitly specify the categories order "
"by passing in a categories argument."
) from err
if preserve_object:
# GH#61778 wrap categories in an Index to prevent dtype
# inference in the CategoricalDtype constructor
from pandas import Index
categories = Index(categories, dtype=object, copy=False)
# if not preserve_object, we're inferring from values
dtype = CategoricalDtype(categories, dtype.ordered)
elif isinstance(values.dtype, CategoricalDtype):
old_codes = extract_array(values)._codes
codes = recode_for_categories(View on GitHub (pinned to 3b7651241d)