{"record":{"id":"9643e0caa308d25d","repo":"pandas-dev/pandas","slug":"categorical-is-not-ordered-for-operation-op-you","errorCode":null,"errorMessage":"Categorical is not ordered for operation {op}\nyou can use .as_ordered() to change the Categorical to an ordered one\n","messagePattern":"Categorical is not ordered for operation (.+?)\nyou can use \\.as_ordered\\(\\) to change the Categorical to an ordered one\n","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/categorical.py","lineNumber":2011,"sourceCode":"            categorical.categories.dtype.\n        \"\"\"\n        # if we are a datetime and period index, return Index to keep metadata\n        if needs_i8_conversion(self.categories.dtype):\n            return self.categories.take(\n                self._codes, allow_fill=True, fill_value=NaT\n            )._values\n        elif is_integer_dtype(self.categories.dtype) and -1 in self._codes:\n            return (\n                self.categories.astype(\"object\")\n                .take(self._codes, allow_fill=True, fill_value=np.nan)\n                ._values\n            )\n        return np.array(self)\n\n    def check_for_ordered(self, op) -> None:\n        \"\"\"assert that we are ordered\"\"\"\n        if not self.ordered:\n            raise TypeError(\n                f\"Categorical is not ordered for operation {op}\\n\"\n                \"you can use .as_ordered() to change the \"\n                \"Categorical to an ordered one\\n\"\n            )\n\n    def argsort(\n        self, *, ascending: bool = True, kind: SortKind = \"quicksort\", **kwargs\n    ) -> npt.NDArray[np.intp]:\n        \"\"\"\n        Return the indices that would sort the Categorical.\n\n        Missing values are sorted at the end.\n\n        Parameters\n        ----------\n        ascending : bool, default True\n            Whether the indices should result in an ascending\n            or descending sort.","sourceCodeStart":1993,"sourceCodeEnd":2029,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/categorical.py#L1993-L2029","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ns = pd.Series(pd.Categorical(['low','high','med']))\ns.min()  # TypeError: Categorical is not ordered\n\n// after\ns = s.cat.as_ordered()\ns.min()  # 'high' -> actually 'low' given default alpha sort; use explicit categories\ns = pd.Series(pd.Categorical(['low','med','high'], categories=['low','med','high'], ordered=True))\ns.min()  # 'low'","handlingStrategy":"validation","validationCode":"def ensure_ordered(s):\n    import pandas as pd\n    if isinstance(s.dtype, pd.CategoricalDtype) and not s.cat.ordered:\n        return s.cat.as_ordered()\n    return s","typeGuard":"import pandas as pd\nfrom typing import Any\n\ndef is_ordered_categorical(obj: Any) -> bool:\n    dt = getattr(obj, 'dtype', None)\n    return isinstance(dt, pd.CategoricalDtype) and dt.ordered","tryCatchPattern":"try:\n    s.min()\nexcept TypeError as e:\n    if 'not ordered for operation' in str(e):\n        s = s.cat.as_ordered()\n    else:\n        raise","preventionTips":["Create ordinal labels with pd.Categorical(data, categories=[...], ordered=True).","Guard min/max/median/rank calls behind an ordered check for category columns."],"tags":["categorical","ordered","min-max"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}