{"record":{"id":"c0c43ffd8ef8cb39","repo":"pandas-dev/pandas","slug":"new-categories-need-to-have-the-same-number-of-ite","errorCode":null,"errorMessage":"new categories need to have the same number of items as the old categories!","messagePattern":"new categories need to have the same number of items as the old categories!","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/categorical.py","lineNumber":987,"sourceCode":"        >>> c\n        ['a', 'b']\n        Categories (2, str): ['a', 'b']\n\n        >>> c._set_categories(pd.Index([\"a\", \"c\"]))\n        >>> c\n        ['a', 'c']\n        Categories (2, str): ['a', 'c']\n        \"\"\"\n        if fastpath:\n            new_dtype = CategoricalDtype._from_fastpath(categories, self.ordered)\n        else:\n            new_dtype = CategoricalDtype(categories, ordered=self.ordered)\n        if (\n            not fastpath\n            and self.dtype.categories is not None\n            and len(new_dtype.categories) != len(self.dtype.categories)\n        ):\n            raise ValueError(\n                \"new categories need to have the same number of \"\n                \"items as the old categories!\"\n            )\n\n        super().__init__(self._ndarray, new_dtype)\n\n    def _set_dtype(self, dtype: CategoricalDtype, *, copy: bool) -> Self:\n        \"\"\"\n        Internal method for directly updating the CategoricalDtype\n\n        Parameters\n        ----------\n        dtype : CategoricalDtype\n\n        Notes\n        -----\n        We don't do any validation here. It's assumed that the dtype is\n        a (valid) instance of `CategoricalDtype`.","sourceCodeStart":969,"sourceCodeEnd":1005,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/categorical.py#L969-L1005","documentation":"Raised by the `rename_categories`/`set_categories(fastpath=...)` path when the new categories collection has a different length than the existing categories. Renaming is a 1-to-1 relabeling of codes — the cardinality must stay identical so each existing code keeps a target label.","triggerScenarios":"Calling `cat.rename_categories(['x', 'y'])` on a Categorical with 3 (or 1) current categories; passing a dict to rename that omits some categories when length semantics apply.","commonSituations":"Renaming labels after a refactor where the set of categories also changed; off-by-one in replacement lists; confusing `rename_categories` with `set_categories` (the latter allows size changes).","solutions":["Use `cat.set_categories(new_list)` instead — it intentionally allows a different cardinality (existing codes that no longer map become NaN).","Provide a replacement list whose length equals `len(cat.categories)`.","Use a dict mapping old→new with `rename_categories` for partial renames (keys must cover all current categories).","Verify `len(new_categories) == len(cat.categories)` before calling rename."],"exampleFix":"# before\ncat = pd.Categorical(['a', 'b', 'c'])\ncat = cat.rename_categories(['x', 'y'])  # ValueError\n\n# after (rename, full mapping)\ncat = cat.rename_categories({'a': 'x', 'b': 'y', 'c': 'z'})\n# after (replace categories entirely, size may change)\ncat = cat.set_categories(['x', 'y'])","handlingStrategy":"validation","validationCode":"def safe_rename(cat, new_categories):\n    new_categories = list(new_categories)\n    if len(new_categories) != len(cat.categories):\n        return cat.set_categories(new_categories)  # intentional size change\n    return cat.rename_categories(new_categories)","typeGuard":"def is_one_to_one_rename(cat, new_categories) -> bool:\n    return len(list(new_categories)) == len(cat.categories)","tryCatchPattern":"try:\n    cat = cat.rename_categories(new_list)\nexcept ValueError as e:\n    if 'same number of items' in str(e):\n        cat = cat.set_categories(new_list)\n    else:\n        raise","preventionTips":["Check `len(new) == len(cat.categories)` before `rename_categories`.","Use `set_categories` when the cardinality is intentionally changing.","Use a dict for `rename_categories` to make partial renames explicit."],"tags":["categorical","rename-categories","cardinality","valueerror"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}