From 2591fa4e3291e70c3dc3c84ca2bb8cc4132f32f4 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 15 Dec 2020 18:24:05 -0800 Subject: [PATCH 1/2] Use astype_nansafe in Index.astype --- pandas/core/indexes/base.py | 27 +++++++++++++++++---------- pandas/core/indexes/numeric.py | 19 ------------------- 2 files changed, 17 insertions(+), 29 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index bafb37775cbb1..f900f01ae9b88 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -33,6 +33,7 @@ from pandas.util._decorators import Appender, cache_readonly, doc from pandas.core.dtypes.cast import ( + astype_nansafe, find_common_type, maybe_cast_to_integer_array, maybe_promote, @@ -693,22 +694,28 @@ def astype(self, dtype, copy=True): if is_dtype_equal(self.dtype, dtype): return self.copy() if copy else self - elif is_categorical_dtype(dtype): - from pandas.core.indexes.category import CategoricalIndex - - return CategoricalIndex( - self._values, name=self.name, dtype=dtype, copy=copy + if needs_i8_conversion(dtype) and is_float_dtype(self.dtype): + # We can't put this into astype_nansafe bc astype_nansafe allows + # casting np.nan to NaT + raise TypeError( + f"Cannot convert {type(self).__name__} to dtype {dtype}; integer " + "values are required for conversion" ) - elif is_extension_array_dtype(dtype): - return Index(np.asarray(self), name=self.name, dtype=dtype, copy=copy) - try: - casted = self._values.astype(dtype, copy=copy) - except (TypeError, ValueError) as err: + casted = astype_nansafe(self._values, dtype=dtype, copy=True) + except ValueError as err: + if "Cannot cast int64 dtype to" in str(err): + # FIXME: kludge; raised via Categorical astype + casted = self._values.astype(dtype, copy=copy) + else: + raise + + except TypeError as err: raise TypeError( f"Cannot cast {type(self).__name__} to dtype {dtype}" ) from err + return Index(casted, name=self.name, dtype=dtype) _index_shared_docs[ diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index 91d27d9922aa5..d6f91c9a06739 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -7,12 +7,10 @@ from pandas._typing import Dtype, DtypeObj, Label from pandas.util._decorators import doc -from pandas.core.dtypes.cast import astype_nansafe from pandas.core.dtypes.common import ( is_bool, is_bool_dtype, is_dtype_equal, - is_extension_array_dtype, is_float, is_float_dtype, is_integer_dtype, @@ -21,8 +19,6 @@ is_scalar, is_signed_integer_dtype, is_unsigned_integer_dtype, - needs_i8_conversion, - pandas_dtype, ) from pandas.core.dtypes.generic import ABCSeries from pandas.core.dtypes.missing import is_valid_nat_for_dtype, isna @@ -332,21 +328,6 @@ def inferred_type(self) -> str: """ return "floating" - @doc(Index.astype) - def astype(self, dtype, copy=True): - dtype = pandas_dtype(dtype) - if needs_i8_conversion(dtype): - raise TypeError( - f"Cannot convert Float64Index to dtype {dtype}; integer " - "values are required for conversion" - ) - elif is_integer_dtype(dtype) and not is_extension_array_dtype(dtype): - # TODO(jreback); this can change once we have an EA Index type - # GH 13149 - arr = astype_nansafe(self._values, dtype=dtype) - return Int64Index(arr, name=self.name) - return super().astype(dtype, copy=copy) - # ---------------------------------------------------------------- # Indexing Methods From 18274b42da68dd4b4cd8f2b14ed65aba9ef312b4 Mon Sep 17 00:00:00 2001 From: Brock Date: Tue, 15 Dec 2020 20:06:37 -0800 Subject: [PATCH 2/2] remove unnecesary error handling --- pandas/core/indexes/base.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index f900f01ae9b88..2101893d39dc9 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -704,13 +704,6 @@ def astype(self, dtype, copy=True): try: casted = astype_nansafe(self._values, dtype=dtype, copy=True) - except ValueError as err: - if "Cannot cast int64 dtype to" in str(err): - # FIXME: kludge; raised via Categorical astype - casted = self._values.astype(dtype, copy=copy) - else: - raise - except TypeError as err: raise TypeError( f"Cannot cast {type(self).__name__} to dtype {dtype}"