{"record":{"id":"2958cb277e2ce7d2","repo":"pandas-dev/pandas","slug":"cannot-convert-float-nan-to-integer","errorCode":null,"errorMessage":"Cannot convert float NaN to integer","messagePattern":"Cannot convert float NaN to integer","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/categorical.py","lineNumber":623,"sourceCode":"            # GH 10696/18593/18630\n            dtype = self.dtype.update_dtype(dtype)\n            self = self.copy() if copy else self\n            result = self._set_dtype(dtype, copy=False)\n            wrong = result.isna() & ~self.isna()\n            if wrong.any():\n                warnings.warn(\n                    \"Constructing a Categorical with a dtype and values containing \"\n                    \"non-null entries not in that dtype's categories is deprecated \"\n                    \"and will raise in a future version.\",\n                    Pandas4Warning,\n                    stacklevel=find_stack_level(),\n                )\n\n        elif isinstance(dtype, ExtensionDtype):\n            return super().astype(dtype, copy=copy)\n\n        elif dtype.kind in \"iu\" and self.isna().any():\n            raise ValueError(\"Cannot convert float NaN to integer\")\n\n        elif len(self.codes) == 0 or len(self.categories) == 0:\n            # For NumPy 1.x compatibility we cannot use copy=None.  And\n            # `copy=False` has the meaning of `copy=None` here:\n            if not copy:\n                result = np.asarray(self, dtype=dtype)\n            else:\n                result = np.array(self, dtype=dtype)\n\n        else:\n            # GH8628 (PERF): astype category codes instead of astyping array\n            new_cats = self.categories._values\n\n            try:\n                new_cats = new_cats.astype(dtype=dtype, copy=copy)\n                fill_value = self.categories._na_value\n                if not is_valid_na_for_dtype(fill_value, dtype):\n                    fill_value = lib.item_from_zerodim(","sourceCodeStart":605,"sourceCodeEnd":641,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/categorical.py#L605-L641","documentation":"Raised in `Categorical.astype` when the target dtype is an integer kind (`'i'`/`'u'`) but the categorical contains missing values (NaN, coded internally as `-1`). NumPy integer arrays cannot represent NaN, so conversion is refused rather than silently producing garbage values.","triggerScenarios":"`cat.astype('int64')` (or `int32`, `uint16`, etc.) on a Categorical that has any `NaN`/missing entry, or `pd.Categorical([1.0, None]).astype(int)`.","commonSituations":"Cleaning columns where missing integers were stored as categoricals; converting survey codes back to ints without handling non-responses; pandas ↔ nullable-extension interop where users assume `astype('int')` will just work.","solutions":["Drop or fill missing values first: `cat.dropna().astype('int64')` or `cat.fillna(0).astype('int64')`.","Convert to a nullable integer dtype: `cat.astype('Int64')` (pandas nullable extension type).","Cast to float instead if NaN must be preserved: `cat.astype('float64')`.","Map codes directly if you want raw integer codes: `cat.codes` (already an int8/16/32 with -1 for NaN)."],"exampleFix":"# before\ncat = pd.Categorical([1, 2, None])\narr = cat.astype('int64')  # ValueError\n\n# after (nullable)\narr = cat.astype('Int64')\n# after (drop NaN)\narr = cat.dropna().astype('int64')","handlingStrategy":"validation","validationCode":"def to_int_safe(cat):\n    if cat.isna().any():\n        raise ValueError('Categorical has NaN; use .astype(\"Int64\") or fillna first')\n    return cat.astype('int64')","typeGuard":"def has_no_missing(cat) -> bool:\n    return not cat.isna().any()","tryCatchPattern":"try:\n    arr = cat.astype('int64')\nexcept ValueError as e:\n    if 'Cannot convert float NaN' in str(e):\n        arr = cat.astype('Int64')  # nullable\n    else:\n        raise","preventionTips":["Use the nullable `Int64`/`Int32` dtypes when missing values must survive a cast.","Drop or impute missing entries before casting to a numpy integer dtype.","Inspect `cat.isna().any()` before any integer cast."],"tags":["categorical","astype","integer","missing-values","valueerror"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}